1.(TCP)面向连接的套接字
不管你采用的是哪种地址家族,都有两种不同风格的套接字连接。第一种是面向连接的
这意味着在进行通信之前必须先建立一个连接,例如,使用电话系统给一个朋友打电话。这
种类型的通信也称为虚拟电路或流套接字。48 第 1 部分 通用应用主题
面向连接的通信提供序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本
上意味着每条消息可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地,然后
将它们按顺序组合在一起,最后将完整消息传递给正在等待的应用程序。
实现这种连接类型的主要协议是传输控制协议(更为人熟知的是它的缩写 TCP)。为 了
创建 TCP 套接字,必须使用 SOCK_STREAM 作为套接字类型。TCP 套接字的名字
SOCK_STREAM 基于流套接字的其中一种表示。因为这些套接字(AF_INET)的网络版本
使用因特网协议(IP)来搜寻网络中的主机,所以整个系统通常结合这两种协议(TCP 和 IP)
来进行(当然,也可以使用 TCP 和本地[非网络的 AF_LOCAL/AF_UNIX]套接字,但是很明
显此时并没有使用 IP)。
2.(UDP)无连接的套接字
与虚拟电路形成鲜明对比的是数据报类型的套接字,它是一种无连接的套接字。这意味
着,在通信开始之前并不需要建立连接。此时,在数据传输过程中并无法保证它的顺序性、
可靠性或重复性。然而,数据报确实保存了记录边界,这就意味着消息是以整体发送的,而
并非首先分成多个片段,例如,使用面向连接的协议。
使用数据报的消息传输可以比作邮政服务。信件和包裹或许并不能以发送顺序到达。
事实上,它们可能不会到达。为了将其添加到并发通信中,在网络中甚至有可能存在重复
的消息。
既然有这么多副作用,为什么还使用数据报呢(使用流套接字肯定有一些优势)?由于面
向连接的套接字所提供的保证,因此它们的设置以及对虚拟电路连接的维护需要大量的开销。
然而,数据报不需要这些开销,即它的成本更加“低廉”。因此,它们通常能提供更好的性能,
并且可能适合一些类型的应用程序。
实现这种连接类型的主要协议是用户数据报协议(更为人熟知的是其缩写 UDP)。为 了
创建 UDP 套接字,必须使用 SOCK_DGRAM 作为套接字类型。你可能知道,UDP 套接字的
SOCK_DGRAM 名字来自于单词“datagram”(数据报)。因为这些套接字也使用因特网协议
来寻找网络中的主机,所以这个系统也有一个更加普通的名字,即这两种协议(UDP 和 IP)
的组合名字,或 UDP/IP。
TCP服务端客户端实例
from socket import *
IP = '0.0.0.0'
PORT = 1314
BUFLEN = 512
ssk = socket(AF_INET, SOCK_STREAM)
ssk.bind((IP,PORT))
ssk.listen(5)
print("服务端启动成功,等待客户端连接。。。")
tsk, addr = ssk.accept()
print("接受客户端连接:",addr)
while True:
#接受客户端返回的字节码
recved = tsk.recv(BUFLEN)
if not recved:
break
message = recved.decode()#解码成str
print (f'收到对方信息:{message}')
# print('收到对方信息:{message}')
tsk.send(f"服务端收到了信息{message}".encode())#编码字符串
tsk.close()
ssk.close()
from socket import *
IP = '127.0.0.1'
SERVER_PORT = 1314
BUFLEN = 512
tsk = socket(AF_INET, SOCK_STREAM)
tsk.connect((IP, SERVER_PORT))
while True:
toSend = input('>>> ')
if toSend == 'byebye':
break
tsk.send(toSend.encode())
recved = tsk.recv(BUFLEN)
if not recved:
break
print(recved.decode())
tsk.close()
2.UDP服务端和客户端
from socket import * #导入socket
from time import ctime
print("---------------------------服务端udp------------------------------------")
#设置端口,地址
PORT = 520
IP = '0.0.0.0'
MAX = 1024
#创建socket对象
usk = socket(AF_INET,SOCK_DGRAM)
#绑定端口地址
usk.bind((IP,PORT))
print("服务端启动成功")
#信息传输
while True:
#接收信息
data,addr = usk.recvfrom(MAX)
print("连接成功,等待对方发送信息")
usk.sendto(('[%s] %s' %(ctime(),data)).encode(),addr)
usk.close()
from socket import * #导入socket
print("---------------------------客户端udp------------------------------------")
#端口地址
PORT = 520
IP= '127.0.0.1'
MAX = 1024
#创建
psk = socket(AF_INET,SOCK_DGRAM)
# #连接
# psk.connect((IP,PORT))
while True:
data = input('>')
if not data:
break
psk.sendto(data.encode(),(IP,PORT))
data,(IP,PORT) = psk.recvfrom(MAX)
if not data:
break
print(data)
psk.close()