文章简介:
- TCP和UDP套接字通信的特点
- TCP客户端与服务器
- UDP客户端与服务器
TCP和UDP套接字通信特点
TCP套接字是面向连接的套接字,这意味着在开始通信之前必须先建立一个连接。
UDP套接字是无连接的套接字,也称为数据报,即在开始通信之前并不需要建立连接。
面向连接的套接字提供一种序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本上意味着每条消息可以拆分成多个片段,并且每一条消息都能够到达目的地,然后它们将按照顺序组合在一起,最后将完整的消息传递给正在等待的应用程序。
反之,无连接的套接字在数据传输过程中无法保证它的顺序性、可靠性和不重复性,并且在数据传输过程中还有可能出现数据丢失的情况。但是,数据报确实保存了边界,这就意味着消息是以整体发送的,并不会分成多个片段,同时,相对于面向连接到套接字,无连接套接字的开销更低,成本也更加低廉,通常能够提供更好的性能。
TCP客户端与服务器
- TCP客户端
首先,来看TCP服务器的代码
#coding:utf-8
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024 #设置数据缓冲区大小
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM) #创建套接字
tcpSerSock.bind(ADDR) #绑定套接字地址
tcpSerSock.listen(5) #打开监听
while True:
print('waiting for connection...')
tcpCliSock, addr = tcpSerSock.accept() #接收客户端的连接
print('...connected from:', addr)
while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data)
data_1 = input('> ')
tcpCliSock.send(data_1.encode('utf-8'))
tcpCliSock.close()
HOST = 'localhost'
PORT = 21567
此处HOST和PORT的设置都是服务器的IP地址。
tcpSerSock.listen(5) #打开监听
tcpCliSock, addr = tcpSerSock.accept() #接收客户端的连接
这个独立的服务器套接字(tcpCliSock)负责与客户端通信,这样就可以空出原始的客户端套接字(tcpSerSock),服务器就可以继续接收其他客户端的连接请求。
接收得到的地址(addr)是客户端的IP地址。
- TCP服务器
#coding:utf-8
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data = input('>')
if not data:
break
tcpCliSock.send(data.encode('utf-8'))
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data)
tcpCliSock.close()
HOST = 'localhost'
此处变量HOST需注意,因为客户端与服务器在同一台计算机上,所以此处的HOST是本地主机名。如果客户端和服务器不在同一主机上,那么HOST参数必须设置成相应的服务器所在的主机名。
如果使用WINDOWS系统,那么可直接在CMD环境下执行客户端和服务器。
在CMD下切换目录至客户端和服务器文件所在目录,然后可按照如下命令运行服务器和客户端(先运行服务器,然后运行客户端)
服务器运行效果
客户端运行效果
UDP客户端与服务器
- UDP服务器
UDP服务器不是面向连接的,因此不需要TCP服务器那么多设置。
我们先来看UDP服务器的伪代码
ss = socket()#创建服务器套接字
ss.bind()#绑定服务器套接字
ifn_loop:
cs = ss.recvfrom()/ss.sendto()#服务器无限循环,接收发送数据
ss.close()#关闭服务器套接字
from socket import *
HOST = 'localhost'
PORT = 21567
BUFISE = 1024
ADDR = (HOST, PORT)
udpSerSock = socket(AF_INET, SOCK_DGRAM)#创建套接字
udpSerSock.bind(ADDR)
while True:
print('waiting for message...')
data, addr = udpSerSock.recvfrom(BUFISE)
print(data)
data_1 = input('> ')
udpSerSock.sendto(data_1.encode('utf-8'), addr)
print('...received from and returned to:', addr)
同样的,recvfrom函数返回连接服务器的客户端的地址和接收到的数据。
- UDP客户端
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
udpCliSock = socket(AF_INET, SOCK_DGRAM)
while True:
data = input('> ')
if not data:
break
udpCliSock.sendto(data.encode('utf-8'), ADDR)
data, ADDR = udpCliSock.recvfrom(BUFSIZE)
if not data:
break
print(data)
udpCliSock.close()