一、网络编程
1.1 TCP 客户端程序开发流程
- 创建客户端套接字对象
- 和服务端套接字建立连接
- 发送数据
- 接收数据
- 关闭客户端套接字
1.2 TCP 服务端程序开发流程
步骤说明:
- 创建服务端端套接字对象
- 绑定端口号
- 设置监听
- 等待接受客户端的连接请求
- 接收数据
- 发送数据
- 关闭套接字
1.3 TCP 客户端程序开发
客户端尝试连接服务端, 不停向服务端发送数据,并且使用select 非阻塞IO监听是否有数据,当接收到数据为空则表示服务器已经下线,则重新尝试连接
import socket
import time
import select
SERVER_IP = "192.168.2.243"
SERVER_PORT = 8090
sendtime =0
isConnected = False
if __name__ == '__main__':
# 创建tcp客户端套接字
# 1. AF_INET:表示ipv4
# 2. SOCK_STREAM: tcp传输协议
while True:
if isConnected == False:
try:
print("try to connect server !")
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_client_socket.connect((SERVER_IP, SERVER_PORT))
except:
isConnected = False
time.sleep(1)
continue
else:
isConnected = True
print("connect %s ok!" %(SERVER_IP,))
sendtime += 1
send_data = f"Hello world-- {sendtime} times!".encode("gbk")
tcp_client_socket.send(send_data)
inputs =[tcp_client_socket]
rs, ws, es = select.select(inputs, [], [],0.3)
for r in rs:
if r is tcp_client_socket:
try:
msg=tcp_client_socket.recv(2048)
except socket.error as error:
print("server disconnect!")
tcp_client_socket.close()
isConnected = False # 断开了连接
break
else: #接收成功
if not msg:
isConnected = False # 断开了连接
tcp_client_socket.close()
print("server disconnect!")
break
else:
print(f'Recv msg {msg} from server {SERVER_IP}')
1.4 多连接服务器开发-子线程实现
子线程设置为守护线程,避免主线程无法退出
建立子线程接收数据,避免 主线程调用recv函数阻塞
acept 返回2个值 : 客户端socket 和地址
import socket
import threading
# 处理客户端的请求操作
def handle_client_request(service_client_socket, ip_port):
# 循环接收客户端发送的数据
while True:
#阻塞接受客户端数据
recv_data = service_client_socket.recv(1024)
#通过容器判断是否接收为空,为空 表示客户端已经断开连接。
if recv_data:
print(recv_data.decode("gbk"), ip_port)
# 回复
service_client_socket.send("ok,问题已经收到...".encode("gbk"))
else:
print("客户端下线了:", ip_port)
break
# 终止和客户端进行通信
service_client_socket.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(("", 8989))
tcp_server_socket.listen(128)
while True:
# 等待接收客户端的连接请求
service_client_socket, ip_port = tcp_server_socket.accept()
print("客户端连接成功:", ip_port)
# 建立子线程,避免 调用recv函数阻塞
sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
# 设置守护线程,防止主线程无法退出
sub_thread.setDaemon(True)
# 启动子线程
sub_thread.start()
1.5 多连接服务器开发-select实现
import socket
import select
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(("", 8989))
tcp_server_socket.listen(128)
input_conn =[tcp_server_socket] #客户端的进来的连接
while True:
# 等待接收客户端的连接请求
rs,ws,es = select.select(input_conn,[],[],0.3)
for r in rs:
if tcp_server_socket is r: #表示有客户端连接进来
client_conn, addr= tcp_server_socket.accept()
input_conn.append(client_conn)
print("new connection from {}".format(addr))
else: # 表示客户端有数据
try:
msg = r.recv(2048)
except socket.error as error:
input_conn.remove(r)
print("{} disconnect ".format(r.getpeername()))
break
else:
if not msg: #消息为空则表示已经断开了连接
input_conn.remove(r)
print("{} disconnect ".format(r.getpeername()))
else:
print("Recv msg {} from server ".format(msg))