ChuannBlog

Socket网络编程

1 基础知识

客户端/服务器架构(C/S)

TCP/IP五层协议

2 socket(套接字)

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

2.1 套接字的连接过程

  1. 服务器监听:不指定具体的客户端套接字,处于等待连接的状态,实时监控网络状态
  2. 客户端请求:指由客户端的套接字提出请求,目标是服务器端的套接字,需要指出服务器端套接字的地址和端口号
  3. 连接确认:当服务器端套接字监听到客户端套接字的连接请求,就响应请求建立一个新的进程,并返回客户端服务器的套接字描述,当客户端确认描述,连接就正式建立,服务器端继续处于监听状态

2.2socket模块

```python  
import socket
socket.socket(socket_family, socket_type,protocal=0)
# socket_family 可以是 AF_UNIX 或 AF_INET。
# socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM
# protocol一般不填,默认值为 0。

# 获取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。
# 使用'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。
# 例如:
from socket import *
tcpSock = socket(AF_INET, SOCK_STREAM)
```

2.3 套接字(socket)函数

服务端

客户端

公共用途

面向锁的套接字方法

面向文件的套接字的函数

2.4 基于TCP的套接字

基础实例

连接循环和通信循环

出现OSError: [WinError 10048]

做测试的时候有可能会出现如下错误信息:

OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。

这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址的状态

其中原理有可能是如下几种,请自行了解:

  1. tcp三次握手,四次挥手
  2. syn洪水攻击
  3. 服务器高并发情况下会有大量的time_wait状态的优化方法

解决办法:

2.5 粘包

粘包现象解释

关于tcp和udp协议

TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的。

UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。

tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,而udp是基于数据报的,即便是你输入的是空内容(直接回车),那也不是空消息,udp协议会帮你封装上消息头。

粘包条件

补充

粘包的解决方案

2.6 基于UDP的套接字

2.7 socketserver模块

3 练习:ftp文件上传下载

GitHub地址