当前位置: 首页 > news >正文

Socket:TCP/UDP通信详解

Socket

socket是计算机网络中用于实现进程间通信的一种机制。它提供了一种标准的接口,使得不同主机上的应用程序能够通过网络进行数据交换。Socket编程通常用于实现客户端-服务器模型的网络应用程序。

UDP编程

UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议。与TCP不同,UDP不提供可靠的数据传输机制,也不保证数据包的顺序和完整性。UDP适用于对实时性要求较高但对数据丢失不敏感的应用,如视频流、在线游戏和语音通信等。

UDP服务器端代码示例

from socket import *
server_socket = socket(AF_INET, SOCK_DGRAM)# 创建UDP套接字,AF_INET表示使用IPv4协议,SOCK_DGRAM表示使用UDP协议
server_socket.bind(("127.0.0.1", 6789))
while True:redata, addr = server_socket.recvfrom(1024)# 接收客户端发送的数据,1024表示接收数据的最大字节数print("收到客户端数据:", redata.decode("utf-8"))if redata.decode("utf-8") == "exit":breaksend_data = "服务器已收到数据"server_socket.sendto(send_data.encode("utf-8"), addr)
server_socket.close()
print("服务器已关闭连接")

UDP客户端代码示例

from socket import *
client_socket = socket(AF_INET, SOCK_DGRAM)# 创建UDP套接字,AF_INET表示使用IPv4协议,SOCK_DGRAM表示使用UDP协议
server_address = ("127.0.0.1", 6789)
while True:send_data = input("请输入要发送的数据:")client_socket.sendto(send_data.encode("utf-8"), server_address)if send_data == "exit":breakredata, addr = client_socket.recvfrom(1024)# 接收服务器返回的数据,1024表示接收数据的最大字节数print("收到服务器数据:", redata.decode("utf-8"))
client_socket.close()
print("客户端已关闭连接")

其实例子中,客户端和服务端的代码高度相似,主要区别在于数据的发送和接收方式。UDP协议不需要建立连接,因此客户端可以直接向服务器发送数据,而服务器也可以直接接收来自客户端的数据。所以说,没有十分明显的客户端和服务器端代码区别。

TCP编程

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的传输层协议。它提供可靠的数据传输机制,确保数据包按顺序到达,并且不会丢失或重复。TCP适用于对数据完整性和可靠性要求较高的应用,如文件传输、电子邮件和网页浏览等。

TCP服务器端代码示例

from socket import *
from threading import Threaddef handle_client(client_s, client_addr):print("客户端连接地址:", client_addr)while True:redata = client_s.recv(1024)if not redata:breakprint("收到客户端数据:", redata.decode("utf-8"))if redata.decode("utf-8") == "exit":breaksend_data = "服务器已收到数据"client_s.send(send_data.encode("utf-8"))client_s.close()print("客户端已关闭连接:", client_addr)server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.bind(("127.0.0.1", 6789))
server_socket.listen(5)
print("服务器已启动,等待客户端连接...")
while True:client_socket, client_addr = server_socket.accept()t = Thread(target=handle_client, args=(client_socket, client_addr))t.start()
server_socket.close()
print("服务器已关闭连接")

TCP客户端代码示例

from socket import *
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(("127.0.0.1", 6789))
while True:send_data = input("请输入要发送的数据:")client_socket.send(send_data.encode("utf-8"))if send_data == "exit":breakredata = client_socket.recv(1024)print("收到服务器数据:", redata.decode("utf-8"))
client_socket.close()
print("客户端已关闭连接")

对于上面的代码,运行一个客户端后,再运行多个客户端,可以看到服务器端会为每个客户端创建一个独立的线程来处理通信,从而实现多客户端同时连接和通信的功能。

实现客户端之间的通信

如果想要实现客户端之间的通信,可以通过服务器端进行转发。具体来说,服务器端需要维护一个客户端连接的列表,当一个客户端发送数据时,服务器端将该数据转发给其他所有连接的客户端。这样,客户端之间就可以实现通信了。
服务端

from socket import *
from threading import Threadclients = []  # 用于存储所有连接的客户端套接字def handle_client(client_s, client_addr):username = client_s.recv(1024).decode("utf-8")print(f"客户端连接地址: {client_addr}, 用户名: {username}")broadcast_message(f"{username} 已加入聊天", client_s)while True:redata = client_s.recv(1024).decode("utf-8")if not redata:breakprint("收到", username,"数据:", redata.split(":", 1)[1])if redata == "exit":break# 将收到的数据转发给其他所有客户端broadcast_message(redata, client_s)client_s.close()clients.remove(client_s)print("客户端已关闭连接:", client_addr)def broadcast_message(message, sender_socket):for client in clients:if client != sender_socket:client.send(message.encode("utf-8"))server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.bind(("127.0.0.1", 6789))
server_socket.listen(5)
print("服务器已启动,等待客户端连接...")
while True:client_socket, client_addr = server_socket.accept()clients.append(client_socket)  # 将新连接的客户端套接字添加到列表中t = Thread(target=handle_client, args=(client_socket, client_addr))t.start()
server_socket.close()
print("服务器已关闭连接")

客户端

from socket import *
from threading import Thread
import jsonclient_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(("127.0.0.1", 6789))username = input("请输入用户名:")
client_socket.send(username.encode("utf-8"))def recv_messages():while True:redata = client_socket.recv(1024)if not redata:breakmessage = redata.decode("utf-8")if message == "exit":breakprint(message)def send_messages():while True:send_data = input()if send_data == "exit":client_socket.send(send_data.encode("utf-8"))# Notify server about exitbreakmessage = f"{username}: {send_data}"client_socket.send(message.encode("utf-8"))recv_thread = Thread(target=recv_messages)
send_thread = Thread(target=send_messages)
recv_thread.start()
send_thread.start()

TCP与HTTP的结合

TCP协议是HTTP协议的基础。HTTP(Hypertext Transfer Protocol,超文本传输协议)是一种应用层协议,主要用于在Web浏览器和Web服务器之间传输超文本数据。HTTP协议通常使用TCP作为传输层协议,以确保数据的可靠传输。
在实际应用中,HTTP请求和响应都是通过TCP连接进行传输的。当客户端(如Web浏览器)向服务器发送HTTP请求时,首先会建立一个TCP连接,然后通过该连接发送HTTP请求数据。服务器接收到请求后,会处理请求并生成HTTP响应数据,然后通过同一TCP连接将响应数据发送回客户端。最后,TCP连接可以根据需要保持打开状态以进行后续请求,或者关闭以释放资源。
因此,TCP协议为HTTP协议提供了可靠的数据传输机制,确保HTTP请求和响应数据能够完整、按顺序地到达目的地,从而实现Web应用的正常运行。
示例代码如下:

from socket import *
from threading import ThreadWEBROOT = "../"def handle_client(client_s, client_addr):print("客户端连接地址:", client_addr)with client_s:request = client_s.recv(1024)headers = request.split(b"\r\n")# 因为HTTP请求头是以\r\n分隔的(回车换行)filename = headers[0].split(b" ")[1].decode()#  提取客户端请求的文件名print("客户端请求文件:", filename)if filename == "/":filename = "/index.html"try:with open(WEBROOT + filename, "rb") as f:content = f.read()response = b"HTTP/1.1 200 OK\r\n\r\n" + contentexcept FileNotFoundError:response = b"HTTP/1.1 404 Not Found\r\n\r\n<h1>404 Not Found</h1>"client_s.send(response)with socket(AF_INET, SOCK_STREAM) as server_s:server_s.bind(("127.0.0.1", 6789))server_s.listen(5)print("服务器启动,等待客户端连接...")while True:client_s, client_addr = server_s.accept()t = Thread(target=handle_client, args=(client_s, client_addr))# 创建线程处理客户端请求,target 指定线程函数, args 指定线程函数参数t.start()
http://www.dtcms.com/a/609785.html

相关文章:

  • QT opencv实现高拍仪场景识别物体轮廓的案例详解
  • 广水住房和城乡建设部网站舟山网站建设开发
  • 深度学习打卡第R4周:LSTM-火灾温度预测
  • 最好的营销策划公司做seo网站优化价格
  • 通过Rust高性能异步网络服务器的实现看Rust语言的核心优势
  • 第36节:AI集成与3D场景中的智能NPC
  • 一个基于 LayUI + .NET 开源、轻量的医院住院管理系统
  • StarRocks 4.0:让 Apache Iceberg 数据真正 Query-Ready
  • 网站建设 自己的服务器爬虫python入门
  • android抽屉DrawerLayout在2025的沉浸式兼容
  • 美颜SDK性能优化实战:GPU加速与AI人脸美型的融合开发
  • AndroidStudio历史版本下载
  • Mac抹除重装卡在激活锁?两步快速解锁
  • Java语言是编译型还是解释型| 探究Java的运行机制与性能优化
  • 网站发语音功能如何做广州比较好的网站建设公司
  • 公司网站域名更改怎么做建设行业协会网站发展的建议
  • 【ZeroRange WebRTC】Kinesis Video Streams WebRTC Data Plane WebSocket API 深度解析
  • Docker核心概念、常用命令与实战指南
  • 交换机安全基线整改方式-华为S5700系列
  • Django 接口文档生成:Swagger 与 ReDoc 全面说明
  • Docker K8s VM 简介
  • FPGA教程系列-Vivado中读取ROM中数据
  • 网站怎么添加模块鹿寨建设局网站
  • 响应式外贸网站案例国外ps网站
  • springcloud feign远程调用请求参数对象变成linkhashmap处理
  • “耐达讯自动化Profibus总线光端机在化工变频泵控制系统中的应用与价值解析”
  • centos7.2安装cacti1.2.27
  • 将 vue3 项目打包后部署在 springboot 项目运行
  • 福州短视频seo网站建筑网站首页大图
  • 阿根廷网站后缀毕业设计网站成品