python TCP网络编程 实现简单的客服端和服务器端

TCP网络编程

IP地址

作用: 标识计算机网络中一个主机设备/系统(标识计算机网络通信过程中的收发双方地址)
在同一个计算机网络 IP地址不能重复

端口

  • 概念: 本质就是一个数字, 标识计算机系统系统中一个应用程序(服务)
  • 端口号: 数字 0~65535(2字节 = 16 bit = 2**16)
  • 如果一个程序没有设定端口号, 系统会随机为用户程序分配一个动态端口
  • 在linux 中查看占用某端口的程序用 sudo lsof -i:端口号 来查询
  • 在网络通信过程中一般将 IP 和端口合用

socket 套接字

套接字 在中国台湾被称为 —> 网络插座
sock 底层 封装了 网络通信的功能, 用户使用这个功能完成网络交互就可以了

TCP

Transmission Control Protocol 传输控制协议. 就是一种套接字
特点:
1.面向连接: 通信之前需要先建立连接, 通信, 关闭连接. 类似打电话
2.可靠 保证 发送包安全到达

  • 应答机制 接受方收到了数据恢复应答 ACK
  • 超时传送 发送方启动定时器, 超过一定时间限制就会重发
  • 错误效验 数据+结果 -----> 收到数据对数据进行演算
  • 拥塞控制 发送方会根据实际情况动态调整发送速度,降低丢包率
  • 有序编号 每个包编号

客户端通信流程

需要在linux中安装网络调试助手

import socket


if __name__ == "__main__":
	# 1 创建一个套接字   实例对象=模块.类()  IPV4  基于字节流 
	tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

	# 2. 建立和服务器的连接 面向连接  .connect(服务器地址(IP, 端口))
	server_address = ("172.17.0.1", 8080)
	tcp_socket.connect(server_address)

	# 3. 和服务器通信 发送数据 .send(需要发送的字节<二进制> 数据)
	data = input("请输入需要给小姐姐发送的数据:")
	tcp_socke.send(data.encode())

	# 4.接受数据 返回值 = .recv(本次接受的最大字节)
	# 返回值正常情况下是收到的字节; 如果对方断开连接 收到的就是空数据 b""
	recv_data = tcp_socket.recv(1024)
	if recv_data:
		print("收到了数据%s" % recv_data.decode("utf-8"))
	else:
		print("对方已经下线")

	# 5. 关闭套接字
	tcp_socket.close()

服务器通信过程

需要在linux中安装网络调试助手

import socket
import threading


def func(new_client_socket, client_address):
	"""循环的接受用户的信息 收到 - 恢复   判断下线结束当前代码的执行"""
	while True:
		# 5 客服使用分机和用户通信  
		# 5.1 分机接受来自用户的数据
		recv_data = new_client_socket.recv(1024)
		print("收到了来自客户端 %s 的数据: " % (str(client_address), recv_data.decode())
		# 5.2 判断用户是否已经下线 如果下线就关闭套接字 退出循环; 否则继续
		if not recv_data:
			print("用户已经下线")
			new_client_socket.close()
			break
		# 5.3 使用分机回复消息
		new_client_socket.send(recv.data)


if __name__ == "__main__":
	# 1. 创建一个服务器套接字 专门接受用户的连接请求并转发给分机
	server_socket = socket.socket()
	server_socket_setsockopt(sock.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	# 2. 绑定端口
	local_address = ("", 8888)  # "" 表示本机所有IP
	server_socket.bind(local_address)
	# 3. 监听  开始营业  # 128 表示服务器可以让多个客户等待被服务 不等于服务器可以和多少个用户通信
	server_socket.listen(128)
	while True:
		# 4. 接受用户的请求 , 转接请求到分机
		new_client_socket, client_address = server_socket.accept()
		# (<socket.socket套接字对象  分机个用户通信>, 客户端地址元祖("192.168.154.64", 33062))
		# print(ret)
		print("接收到来自%s的用户连接请求"% str(client_address))
		# 每当有一个新用户连接到服务器, 为他创建一个专门子线程运行 func 函数 处理消息
		thd = threading.Thread(target=func, args=(new_client_socket, client_address))
		thd.start()
		
	

在调试上述代码有可能会出现 OSError: [Errno 98] Address already in use 这个问题, 这个是历史遗留问题,换个端口就好啦

地址重用

产生原因: TCP标准为了保证最后一次ACK能够可靠送达规定,
凡是主动断开连接的一方必须保持套接字资源(端口)一段时间 30s-2min === 2 MSL 时间
导致服务器重启在绑定原有端口就会出现地址被使用的现象

解决: 忽略 2MSL 时间 使用地址重用

解决方案:

  1. set socket option 套接字层面 重用地址 reuse address 1True 表示设置 0False 取消设置

  2. 服务器套接字对象.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 1. 创建一个服务器套接字 专门接受用户的链接请求并转发给分机
server_socket = socket.socket()

# 让服务器可以立即重启 并且绑定原有端口等资源 解决 address in use
server_socket.setsockopt(sock.SOL_SOCKET, socket.SO_REUSEADDR, 1)
发布了56 篇原创文章 · 获赞 17 · 访问量 2146

猜你喜欢

转载自blog.csdn.net/LanlanDeming/article/details/103672831
今日推荐