TCP 是面向有连接的可靠传输协议,来讲讲它的一个 Windows 的基本实现。
学习笔记
首先在 Windows 下 socket 编程要添加这样的预处理:
1 2
| # include<WinSock2.h> # pragma comment(lib,"ws2_32.lib")
|
然后我们需要启动一下,一般加入以下代码即可:
1 2 3
| WORD wVersionRequested = MAKEWORD(2, 2); WSADATA lpWSAData; int nRet = WSAStartup(wVersionRequested, &lpWSAData);
|
为了程序健壮可以添加一些判断代码。
1 2 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,绑定在哪个端口。
这里我们直接
1 2 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 端口。
监听端口
1 2 3
| int len = sizeof(addServer); bind(SockServer, (sockaddr*)&addServer, len); listen(SockServer,5);
|
然后使用 bind 方法去绑定套接字,最后用 listen 方法去监听端口,到这里服务端就完成了。
当然呢连接过来的时候,我们需要给客户端建立一个连接对象,然后对这个对象进行操作就相当于发送数据了,我们发送接收数据使用 send 和 recv 方法。
为了防止 socket 只运行一遍就关闭我们可以 while 1 去处理请求。
1 2 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); }
|
最终代码
1 2 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 去连接看看效果。
服务端运行结果: