计算机网络自顶向下结构——第7版
第二章实验,套接字编程
代码运行环境:window10,python 3.8.对于书上代码略作修改。
多数应用程序是由通信进程队组成的,每对中的两个进程互相发送报文。而从一个进程向另外一个进程发送的报文必须经过下面的网络。进程通过一个称为套接字的软件接口向网络发送报文和从网络接收报文。
简单理解一下:如果把一个进程比作一座房子,那么套接字就可以类比为他的门。当一个进程想要向位于另一台主机上的另一个进程发送报文的时候,他要向把报文推送出门,该发送进程假定该门到门外一侧之间有运输的基础设施,该设施会把报文传送到目的进程的门口。一旦报文抵达目的主机,它就会通过接收进程的门传递,然后接收进程对该报文进行处理。
如上图所示,套接字是同一台主机内层应用程序和网络之间的接口。由于其建立网络应用程序的可编程接口,所以也叫做应用程序和网络之间的应用编程接口(API application programming interface)
应用层虽然可以空hi套接字在顶层应用端的一切,但是对于套接字的运输层几乎没有控制权。嗯,仅限于:选择运输层协议,或者说可以设定几个参数,简单类似于最大缓存最大报文端长度等。
结用上面的理解,
附在分组的目的地址包括:
同样,发送方的IP地址和端口地址也要附在分组中,便于回信——这个操作是由底层操作系统自动完成。
使用简单的客户-服务器应用程序来演示对于UDP和TCP的套接字编程:
UDP套接字流程:
UDPCLient.py
from socket import *
serverName = 'hostname' #这里的hostname使用自己主机的IPv4地址,也可以使用自己电脑的名字
serverPort = 12000
clientSocket = socket(AF_INET,SOCK_DGRAM)#参数的意思可以看我给的两个博客
message = input('Input lowercases sentence:')
clientSocket.sendto(message.encode(),(serverName,serverPort))
modifiedMessage,serverAddress = clientSocket.recvfrom(2048)
print(modifiedMessage.decode())
clientSocket.close()
AF_INET域与AF_UNIX域socket通信原理对比
流式套接字(SOCK_STREAM),数据报套接字 (SOCK_DGRAM) 的比较
from socket import *
serverPort = 12000
serverScoket = socket(AF_INET,SOCK_DGRAM)
serverScoket.bind(('',serverPort))
print("The server is ready to receive")
while True:
message, clientAddress =serverScoket.recvfrom(2048)
modifiedMessage = message.decode().upper()
serverScoket.sendto(modifiedMessage.encode(), clientAddress)
关闭server:
TCP套接字编程
TCP是一个面向连接的协议。
意味着客户与服务器开始交换数据之前必须建立一个TCP连接。
创建TCP连接时,我们将客户套接字地址于服务器套接字地址关联起来。使用连接时,当一次要向另外一侧发送数据时,他只需要经过其套接字将数据丢进TCP连接。这就与UDP不同,UDP服务器将数据丢进套接字前必须附加一个目的地址。
TCP交互
客服具有向服务器发起接触的任务。服务器为了能够对客户的初始接触做出反应,服务器必须提前准备好。这意味着:
在服务器运行的时候,客户创建一个TCP套接字即可以向服务器发起一个TCP连接。客户生成套接字时,指定了服务器套接字的地址,即服务主机IP和其套接字端口。然后发起三次握手并创建一份与服务器的TCP连接。
发送在运输层的三次握手,对于客户和服务器程序来说是完全透明的。
服务器在第一次收到客户的接触(knock the door)时,他会新生成一个套接字,用于特定的用户。新生成的套接字也叫做连接套接字。
通信过程
TCPClient.py
from socket import *
serverName = 'servername'
serverPort = 12000
clientSocket = socket(AF_INET,SOCK_STREAM)
clientScoket.connect((serverName,serverPort))
sentence = raw_input('Input lowercase sentence:')
clientSocket.send(sentence.encode())
modiefiedSentence = clientSocket.recv(1024)
print('From Server: ',modifiedSentence.decode())
clientSocket.close()
#TCPServer.py
from socket import *
serverPort = 12000
serverSocket=socket(AF_INET,SOCK_STREAM)
serverSocket.bind(('',serverPort))
serverSocket.listen(1)
print('The server is ready to receive')
while True:
connectionSocket,addr = serverSocket.accept()
sentence = connectionSocket.recv(1024).decode()
capitalizedSentence = sentence.upper()
connectionSocket.send(capitalizedSentence.encode())
connectionSocket.close()
运行结果
关闭server: