背景:前段时间做毕设需要做一个显示界面将摄像头采集的关键信息传送回PC并显示出来,由于之前学习java的时候接触过套接字。因此,在利用Python实现这个功能时首先也想到了这茬。想到之后可能还会用到这个知识点,特此记录下来以便翻阅。
TCP套接字
TCP套接字也叫面向连接的套接字,这种连接方式能够保证每一条消息片段都能到达目的地。相对于另一种无连接的套接字(也叫UDP套接字),TCP套接字传输更稳定,开销相对也比UDP套接字要大。
下面给出TCP套接字Python实现的伪代码框架:
服务器端:
ss = socket() #创建服务器套接字
ss.bind() #套接字与地址绑定
ss.listen() #监听连接
inf_loop: #服务器无线循环
cs = ss.accept() #接收客户端连接
comm_loop: #通信循环
cs.recv()/cs.send() #对话(接收/发送)
cs.close() #关闭客户端套接字
ss.close() #关闭服务器(可选)
客户端:
cs = socket()
cs.connect()
comm_loop:
cs.send()/cs.recv()
cs.close()
接下来根据上面的伪代码给出TCP套接字实现的demo,客服端发送数据,服务端收到数据之后,返回收到的时间戳和数据给客户端。
服务器端:
import socket
import time
HOST = ''#空白的host是对bind()方法的标识,表示可以使用任何可用的地址
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)
#TCP套接字:SOCK_STREAM UDP套接字:SOCK_DGRAM
tcpSerSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#AF_INET代表ipv4
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)#该方法的参数是在连接被转接或拒绝之前,传入连接请求的最大数
while True:
print('Waitting for connection...')
tcpCliSock,addr = tcpSerSock.accept()#返回一个新的套接字对象
print('...connected from:{:}'.format(addr))
while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:#如果为空,对话结束
break
tcpCliSock.send('{:} {:}'.format(time.ctime(),data.decode('utf-8')).encode('utf-8'))
tcpCliSock.close()
tcpSerSock.close()
客户端:
import socket
HOST = 'localhost'
PORT = 21567#端口号应该与服务器设置的完全相同,不然无法通信
BUFSIZ = 1024
ADDR = (HOST,PORT)
tcpCliSock = socket.socket(socket.AF_INET,socket.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.decode('utf-8'))
tcpCliSock.close()
TCP套接字
无连接的套接字(也叫UDP套接字),相比于TCP套接字,UDP在通信开始之前不需要建立,在传输过程中也无法保障数据一定会传输成功。但是,相较于TCP套接字,UDP套接字的开销很小。
下面给出UDP套接字Python实现的伪代码框架:
服务器端:
#服务器
ss = socket()
ss.bind()
inf_loop:
cs = ss.recvfrom()/ss.sendto()
ss.close()
客户端:
#客户端
cs = socket()
comm_loop:
cs.sendto()/cs.recvfrom()
cs.close()
接下来根据上面的伪代码给出UDP套接字实现的demo,其功能与上面TCP实现的功能一致,主要点放在二者的对比上。
服务器端:
import socket
import time
HOST = ''
POST = 12580
BUFSIZ = 1024
ADDR = (HOST,POST)
udpSerSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udpSerSock.bind(ADDR)
#由于数据套接字是无连接的,所以没有为了成功通信而使一个客户端连接到一个独立的套接字,这与TCP不同
#同时也没有监听传入的连接
while True:
print('waiting for message...')
data,addr = udpSerSock.recvfrom(BUFSIZ)
udpSerSock.sendto('{:} {:}'.format(time.ctime(),data.decode('utf-8')).encode('utf-8'),addr)
print('...received from and returned to:{:}'.format(addr))
udpSerSock.close()
客户端:
import socket
HOST = 'localhost'
POST = 12580
BUFSIZ = 1024
ADDR = (HOST,POST)
udpCliSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#UDP套接字实现并不需要与服务器建立连接
while True:
data = input('>')
udpCliSock.sendto(data.encode('utf-8'),ADDR)
data,ADDR = udpCliSock.recvfrom(BUFSIZ)
if not data:
break
print(data.decode('utf-8'))
udpCliSock.close()