当初写第一个网络程序的时候,就是通过搜索,找各种实例把程序拼凑出来的,并没有进行深入的理解。这个东西用了这么多年,是该来沉淀一下了,也检验一下自己对这块知识的掌握程度。
可以说,一个典型的网络程序是离不开socket的,它是系统提供给开发者们进行网络操作的强大武器。
socket又叫套接字,是一系列网络操作的API。它的实现和表现形式又会根据系统平台的不同、编程语言的不同而有所区别,但是实现的功能都是一致的。
socket的创建:
windows平台C版本
SOCKET s = socket(AF_.NET, SOCK_STREAM, IPPROTO_TCP);
C#版本
Socket s=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
上面两个套接字都是以TCP协议创建的,socket中的三个参数分别指定了IP层协议类型(IPV4和IPV6),数据交互格式(字节流,数据报等),传输层协议(TCP和UDP)。
套接字在进程中是以文件描述符的形式存在的,其实就是一个数字,用来唯一标识一个套接字,以不同的形式提供给开发者使用。
socket的地址和端口:
地址指定了数据交互节点的设备,如果一台设备有多块网卡,则地址指定的就是某一块网卡;端口标识的是设备上的某个进程。来自网络的数据到达网卡后,向上经过数据链路层,网络层,到达传输层,然后根据端口确定需要将数据交给哪个进程。
数据接收:
数据接收是由进程调用socket的接收函数发起的。该函数会向系统提交接收数据的IO请求,该请求的内容包括应用层存放数据的缓冲区,请求的数据尺寸,在缓冲区中存放数据的偏移值。
C# 发起数据接收请求:
int rcvLen=m_socket.Receive(buf, offset, size, SocketFlags.None);
其中buf为数据缓冲区,offset为数据接收时在buf中存放数据的起始地址,size为此次请求的字节大小,rcvLen为此次接收成功后实际接收到的字节长度。
数据发送:
数据的发送是进程调用socket的发送函数发起的。该函数会向系统提交发送数据的IO请求,向指定的节点发送数据,请求的内容包括发送的数据内容,长度等。
C# 发起的数据发送请求(TCP):
int sndLen= m_socket.Send(buf);
其中buf为发送的内容字节码数组,sndLen为实际发送的字节长度。
TCP Socket:
TCP是传输层的协议,该协议有一定的复杂性,目的是完成数据的可靠传输。采用TCP实现的网络应用,分为服务端和客户端两种端点类型,每个端的实现都对应着不同socket调用函数。
服务端可以接受客户端的连接请求,连接完成后就可以进行双向通信。
建立服务端,需要创建服务端套接字,为该套接字绑定服务地址和端口,打开被动监听,开始等待连接。
C#版本的服务端建立代码
m_socketServer = CreateSocket_IPV4();
m_socketServer.Bind(CreateEndPoint(port, null));
m_socketServer.Listen(10);
m_conns = new List<IConnection>();
Task.Factory.StartNew(() =>
{
while (m_running)
{
var s = m_socketServer.Accept();
var conn = CreateConnection(s);
m_conns.Add(conn);
OnConnected?.Invoke(conn);
}
});
客户端的操作相对简单一些,只需要创建套接字然后向服务端发起连接请求。
C#版本的客户端代码
var s = CreateSocket_IPV4();
s.Connect(IPAddress.Parse(ip), port);
socket涵盖的内容是非常丰富的,我们在此只是拿出一些代表性的内容来记述。