TCP 是面向有连接的可靠传输协议,来讲讲它的一个 Windows 的基本实现。
学习笔记
首先在 Windows 下 socket 编程要添加这样的预处理:
| 12
 
 | # include<WinSock2.h># pragma comment(lib,"ws2_32.lib")
 
 | 
然后我们需要启动一下,一般加入以下代码即可:
| 12
 3
 
 | WORD wVersionRequested = MAKEWORD(2, 2);WSADATA lpWSAData;
 int nRet = WSAStartup(wVersionRequested, &lpWSAData);
 
 | 
为了程序健壮可以添加一些判断代码。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | if (nRet != 0) {printf("WSAStartup Error!\n");
 system("pause");
 return 0;
 }
 if (LOBYTE(lpWSAData.wVersion) != 2 || HIBYTE(lpWSAData.wVersion) != 2) {
 WSACleanup();
 printf("wVersion Error\n");
 return 0;
 }
 
 | 
然后就到了我们最关键的一步了。
建立服务端
创建套接字连接对象
我们先要起一个连接对象,也就是 SOCKET 对象,然后用 socket 方法去创建,socket 方法有三个参数,第一个参数为协议簇,第二个参数为 socket 类型,第三个参数为标志位。
第一个参数就给 AF_INET 表示 IPv4 网络协议的套接字类型,第二个参数给 SOCK_STREAM 表示为流套接字,第三个参数直接给 0 好了。
创建套接字对象
这个对象名为 SOCKADDR_IN。里面有一些成员需要我们设置,我们只需要考虑三个信息:协议簇,绑定在哪个 ip,绑定在哪个端口。
这里我们直接
| 12
 3
 4
 
 | SOCKADDR_IN addServer;addServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
 addServer.sin_family = AF_INET;
 addServer.sin_port = htons(9999);
 
 | 
就把它设置了本地的 9999 端口。
监听端口
| 12
 3
 
 | int len = sizeof(addServer);bind(SockServer, (sockaddr*)&addServer, len);
 listen(SockServer,5);
 
 | 
然后使用 bind 方法去绑定套接字,最后用 listen 方法去监听端口,到这里服务端就完成了。
当然呢连接过来的时候,我们需要给客户端建立一个连接对象,然后对这个对象进行操作就相当于发送数据了,我们发送接收数据使用 send 和 recv 方法。
为了防止 socket 只运行一遍就关闭我们可以 while 1 去处理请求。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | char msg[] = "Hello,You successfully login!!\n";char msg1[] = "I will repeat your message Once\n";
 while (1) {
 SOCKET sockConn = accept(SockServer, (sockaddr*)&addrClient, &len);
 send(sockConn, msg, strlen(msg), 0);
 char buffer[MAX_PATH];
 char SendBuffer[MAX_PATH];
 memset(buffer, 0, sizeof(buffer));
 memset(SendBuffer, 0, sizeof(SendBuffer));
 recv(sockConn, buffer, MAX_PATH, 0);
 sprintf(SendBuffer, buffer);
 
 printf("%s", buffer);
 
 send(sockConn, msg1, strlen(msg1), 0);
 send(sockConn, SendBuffer, strlen(SendBuffer), 0);
 }
 
 | 
最终代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 
 | # include<stdio.h># include<WinSock2.h>
 # pragma comment(lib,"ws2_32.lib")
 int main() {
 WORD wVersionRequested = MAKEWORD(2, 2);
 WSADATA lpWSAData;
 int nRet = WSAStartup(wVersionRequested, &lpWSAData);
 
 
 
 
 
 
 
 
 
 
 SOCKET SockServer = socket(AF_INET, SOCK_STREAM, 0);
 SOCKADDR_IN addServer;
 addServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
 addServer.sin_family = AF_INET;
 addServer.sin_port = htons(9999);
 int len = sizeof(addServer);
 bind(SockServer, (sockaddr*)&addServer, len);
 listen(SockServer,5);
 SOCKADDR_IN addrClient;
 char msg[] = "Hello,You successfully login!!\n";
 char msg1[] = "I will repeat your message Once\n";
 while (1) {
 SOCKET sockConn = accept(SockServer, (sockaddr*)&addrClient, &len);
 send(sockConn, msg, strlen(msg), 0);
 char buffer[MAX_PATH];
 char SendBuffer[MAX_PATH];
 memset(buffer, 0, sizeof(buffer));
 memset(SendBuffer, 0, sizeof(SendBuffer));
 recv(sockConn, buffer, MAX_PATH, 0);
 sprintf(SendBuffer, buffer);
 
 printf("%s", buffer);
 
 send(sockConn, msg1, strlen(msg1), 0);
 send(sockConn, SendBuffer, strlen(SendBuffer), 0);
 }
 }
 
 | 
最后使用 nc 去连接看看效果。
 
服务端运行结果:
