import argparse,socket
def recvall(sock,length):
"""传入一个套接字,和一个长度"""
# 定义一个二进制的变量
data = b''
# 循环
while len(data) < length:
print(len(data),length)
# more用来接收规定长度减去data的长度
# 注意这里,recv函数是阻塞的,如果他没有接收到数据,那么就一直卡在那里。
# 有两种情况,如果每次发送的数据都比我们设定的长度要少,那么第二次循环,就会卡主
# 还有一种就是我们发送的字节数正好是我们规定长度的整数倍,那么最后一次循环就为空了。
# 针对这个,我们可以在发送端和接收端都来一个结束标识。
more = sock.recv(length - len(data))
if more == b'efo':break
if not more:
raise EOFError('was expecting %d bytes but only received '
'd% bytes before the socket closed ' %(length ,len(data)))
data += more
return data
def server(interface,port):
# 定义一个套接字,用于TCP连接
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置套接字连接
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 套接字绑定端口和IP地址
sock.bind((interface,port))
# 设置套接字的监听客户端的监听数量。
sock.listen(1)
# 打印出服务端连接绑定的IP地址和端口
print("listening at",sock.getsockname())
# 死循环遍历,用来重复的进行和监听服务端,然后进行通信。
while True:
# 服务端套接字用来接收客服端的连接请求。
sc,socketname = sock.accept()
print("We have accepted a connection from",socketname)
print(" Socket name:",sc.getsockname())
print(" Socket peer:",sc.getpeername())
# 规定每次接收客户端传过来的消息长度
message = recvall(sc,16)
print('222222')
# 打印出来接受到的数据。
print(' Incoming sixteen-octet message:',repr(message))
# 服务端发送二进制消息。
sc.sendall(b'Farewell,client')
sc.sendall(b'efo')
sc.close()
print(" Reply sent ,scoket closed")
# 定义客户端函数,入参为IP地址和端口
def client(host,port):
# 定义一个TCP 连接的套接字。
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 建立和服务端的TCP连接。
# 注意这里传入的是一个元祖
sock.connect((host,port))
# 打印客户端连接的IP和端口
print('Client has been assigned socket name',sock.getsockname())
# 客户端发送二进制消息
sock.sendall(b'Hi there,server')
# 发送一个结束标识
sock.sendall(b'efo')
# 客户端接收服务端发送过来的消息
reply = recvall(sock,16)
# 打印出来服务端发送的消息
print('222222')
print('The server said' ,repr(reply))
# 关闭套接字
sock.close()
if __name__ == "__main__":
# 定义一个字典
choices = {'client':client,'server':server}
parser = argparse.ArgumentParser(description = 'Send and receive over TCP')
parser.add_argument('role',choices = choices,help = 'which role to play')
parser.add_argument('host',help = 'interface the server listens at;'
' host the client sends to')
parser.add_argument('-p',metavar = "PORT",type = int,default = 1060,help = "TCP port (default 1060")
args = parser.parse_args()
function = choices[args.role]
function(args.host,args.p)