TCP网络应用程序开发流程的介绍
-TCP网络应用程序开发分为:
TCP客户端程序开发
TCP服务端程序开发
-说明:
客户端程序是指运行在用户设备上的程序,服务端程序是指运行在服务器设备上的程序,专门为客户端提供数据服务
TCP客户端程序开发流程的介绍
-创建客户端套接字对象
-和服务端套接字建立连接
-发送数据
-接收数据
-关闭客户端套接字
import socket
if __name__ == '__main__':
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_client_socket.connect(("192.168.1.37", 8080))
send_content = "你好,我是客户端小白!!".encode("gbk")
tcp_client_socket.send(send_content)
recv_content = tcp_client_socket.recv(1024).decode("gbk")
print(recv_content)
tcp_client_socket.close()
TCP服务端程序开发流程的介绍
-创建服务端套接字对象
-绑定端口号
-设置监听
-等待接受客户端的连接请求
-接收数据
-发送数据
-关闭套接字
import socket
if __name__ == '__main__':
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(("", 9090))
tcp_server_socket.listen(128)
new_client, ip_port = tcp_server_socket.accept()
print(f"客户端的IP和端口号为:{ip_port}")
recv_data = new_client.recv(1024).decode("gbk")
print(f"接收客户端的数据为:{recv_data}")
send_content = "好的,我是服务端".encode("gbk")
new_client.send(send_content)
new_client.close()
tcp_server_socket.close()
解决端口号复用的问题
-当客户端与服务端建立连接后,服务端程序退出后端口号不会立即释放,需要等待大概1-2分钟
-解决办法有两种:
更换服务端端口号
设置端口号复用,也就是说让服务端程序退出后端口号立即释放
-设置端口号复用代码如下
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, True)
需求
-目前我们开发的TCP服务端程序只能服务于一个客户端,如何开发一个多任务版的TCP服务端程序能够服务于多个客户端呢?
-完成多任务,可以使用线程,比进程更加节省内存资源
具体实现步骤
-编写一个TCP服务端程序,循环等待接受客户端的连接请求
-当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
-把创建的子线程设置成为守护线程,防止主线程无法退出
import socket
import threading
def handler_client_request(ip_port, new_client):
print(f"客户端的IP和端口号为:{ip_port}")
while True:
recv_data = new_client.recv(1024).decode("gbk")
if recv_data:
print(f"接收客户端的数据为:{recv_data} 此消息来自{ip_port}")
send_content = "好的,我是服务端".encode("gbk")
new_client.send(send_content)
else:
print(f"客户端{ip_port}下线了")
break
new_client.close()
if __name__ == '__main__':
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(("", 9090))
tcp_server_socket.listen(128)
while True:
new_client, ip_port = tcp_server_socket.accept()
sub_thread = threading.Thread(target=handler_client_request, args=(ip_port, new_client))
sub_thread.setDaemon(True)
sub_thread.start()
认识TCP socket的发送和接收缓冲区
-当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区,
这个发送和接收缓冲区指的就是内存中的一片空间
send原理剖析
-send是不是直接把数据发给服务端?
-不是,想要发数据,必须得通过网卡发送数据,应用程序是无法直接通过网卡发送数据的
它需要调用操作系统接口,也就是说,应用程序把发送的数据先写入到发送缓冲区(内存中的一片空间)
再由操作系统控制网卡把发送缓冲区的数据发送给服务端的网卡
recv原理剖析
-recv是不是直接从客户端接收数据?
-不是,应用软件是无法直接通过网卡接收数据的,它需要调用操作系统接口,由操作系统
通过网卡接收数据,把接收的数据写入到接收缓冲区(内存中的一片空间),应用程序
再从接收缓冲区获取客户端发送的数据