TCP
- TCP是一种面向连接,这种连接是一对一的,不适用于广播的应用程序(用udp)
- 与UDP相比,TCP更加稳定可靠
TCP客户端(client)
- 所谓客户端,就相当于被服务的一方
TCP客户端构建
与构建UDP流程类似
1、创建TCP的 socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM) # 当然,前提是先导入socket模块
2、目的信息
server_ip = input("请输入服务器ip:")
server_port = int(input("请输入服务器port:"))
3、链接服务器
tcp_client_socket.connect((server_ip, server_port))
4、发送数据
send_data = input("请输入要发送的数据:")
tcp_client_socket.send(send_data.encode("gbk")) # Windows是"gbk" Linux是"utf-8"
TCP 发送数据用的是
send
»> «< 而UDP发送数据时用的是sendto
5、接受数据
recv_data = tcp_client_socket.recv(1024) # 最大接受为1024个字节
print('接收到的数据为:', recvData.decode('gbk'))
6、关闭 socket (有始有终~)
tcp_client_socket.close()
TCP服务器(server)
- 服务器,顾名思义,服务器就是提供服务的一方
一个简单服务器的搭建
1、 ** **socket 创建一个套接字 (买手机)
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
2、 **bind ** 绑定本地信息 bind(给手机插卡)
tcp_server_socket.bind(("", 7788)) #IP和port
3、 listen 使套接字变为可以被动链接(将手机设置为正常的响铃模式)
tcp_server_socket.listen(128)
4、 accept 等待客户端的链接(等待别人的电话)
new_client_socket, client_addr = tcp_server_socket.accept() # 拆包接受返回的数据
accept()
返回的是一个元组
new_client_socket
是新建的套接字,用来服务链接的客户,旧的套接字继续监听有无新的客户请求
client_addr
是发来链接请求客户的地址信息
5、 recv/send接受发送数据(通话)
recv_data = client_socket.recv(1024) # 接收1024个字节
print('接收到的数据为:', recv_data.decode('gbk'))
# 发送一些数据到客户端
new_client_socket.send("收到请求!".encode('gbk'))
此处
recv
返回的是一个数据(链接客户发来的信息)而
recvfrom
根据词义来看,它返回的除了客户发来的信息外,还有客户的地址信息
6、关闭套接字(通话结束)
new_client_socket.close()
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
因为中途新创建了一个套接字去服务客户,所以最后有两个套接字
TCP服务客户端
import socket
def main():
# 1.创建套接字 socket(买个手机)
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定本地信息 bind(插入手机卡)
tcp_server.bind(("", 7890))
# 3.让默认的套接字由主动变为被动 listen(将手机设置为正常的 响铃模式)
tcp_server.listen(128)
while True:
# 4.等待客户端的链接 accept(等待别人的电话)
print("等待客户链接.....")
new_client_socket, client_addr = tcp_server.accept()
print("收到%s链接" % str(client_addr))
while True:
# 5.接受客户端发送过来的请求
recv_data = new_client_socket.recv(1024)
print("客户端发送来的请求是:%s" % recv_data.decode("gbk"))
# 如果recv解堵塞,那么有两种方式
# >>1.客户端发送过来数据
# >>2.客户端调用close
if not recv_data or recv_data.decode("gbk") == "exit":
break
else:
# 6.回送一部分数据给客户端
new_client_socket.send("收到请求".encode("gbk"))
# 7.关闭套接字
new_client_socket.close()
print("链接服务完毕。")
# 如果将监听套接字关闭了,那么会导致不能在等待新客户端的到来
tcp_server.close()
if __name__ == '__main__':
main()
TCP注意点
- tcp服务器一般情况下都需要绑定,否则客户端找不到这个服务器
- tcp客户端一般不绑定,因为是主动链接服务器,所以只要确定好服务器的ip、port等信息就好,本地客户端可以随机
- tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的
- 当客户端需要链接服务器时,就需要使用connect进行链接,udp是不需要链接的而是直接发送,但是tcp必须先链接,只有链接成功才能通信
- 当一个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
- listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的
- 关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。
- 关闭accept返回的套接字意味着这个客户端已经服务完毕
- 当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线
总结
目前还未用多任务,所以还只能一个一个的客户来服务,等用了多任务,便可多个客户端一起服务