WinSocket 套接字
————服务器与客户端的一般套路
一、开发环境
- IDE: Red Panda Dev-C++ 6.5
- 编程语言:C语言
- 库:winsock2.h
二、套接字工作流程图
注意:这个工作流程图非常重要,后面的代码编写基本就是这个逻辑
三、服务器各部分实现
-
导入头文件
#include<stdio.h> #include<winsock2.h> // 升级版头文件,现在一般都是用这个 // #include<winsock.h> // 原版头文件
-
初始化环境
WSAStartup:在Windows平台上开发socket必写函数,用于允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节。只有调用了该函数window内核才知道你要使用的Socket API的版本号,所以一般都是放到代码之前,而且一般都是固定写法不需要改变。
// 初始化 Socket环境 WSADATA WSAData; if(WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { printf("初始化 Socket环境失败"); return -1; }
-
创建套接字、绑定IP与端口,等待连接
该步骤也基本是套路,只需要改下ip和端口就可以直接使用
// 创建 Server 套接字 SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == server) { perror("创建 Server Socket失败!\n"); return -1; } // 创建并初始化服务器需要绑定IP和端口 char IP[] = "127.0.0.1"; int PORT = 8000; struct sockaddr_in server_addr; // 服务器IP和端口信息 server_addr.sin_family = AF_INET, // 协议为网络协议 server_addr.sin_port = htons(PORT), // 绑定的端口 // 绑定IP地址 server_addr.sin_addr.S_un.S_addr = inet_addr(IP); // 服务器套接字绑定ip和端口 int StatusCode = bind(server, (SOCKADDR*)&server_addr, sizeof(server_addr)); if (SOCKET_ERROR == StatusCode) { perror("Server Socket 绑定IP、端口失败\n"); return -1; } // 开始监听连接, 最多等待的连接数设置为10 listen(server, 10); printf("Server 正在 %s %d 监听连接......\n", IP, PORT);
-
处理连接
该部分基本也是套路,直接照搬
// 接收客户端连接 struct sockaddr_in client_addr; int client_addrlen = sizeof(client_addr); SOCKET client = accept(server, (SOCKADDR*)&client_addr, &client_addrlen); if (SOCKET_ERROR == client) { perror("连接客户端失败\n"); }
-
服务器与客户端交互
该部分是交互部分,需要实现的具体功能就写到该部分,我这里的功能只是将客户端的数据原样返回
// 处理客户端间的连接 char buf[124] = {0}; recv(client, buf, sizeof(buf), 0); // 接收数据 send(client, buf, sizeof(buf), 0); // 发送数据
-
关闭连接
// 关闭连接 closesocket(client); closesocket(server);
-
释放套接字环境
WSACleanup功能与WSAStartup功能相反
// 释放资源 WSACleanup();
如果在编译运行过程中报错,添加只需要在编译时添加上动态库(如下)
四、客户端各部分实现
-
导入头文件
#include<stdio.h> #include<winsock2.h> // 升级版头文件,现在一般都是用这个 // #include<winsock.h> // 原版头文件
-
初始化环境
// 初始化 Socket环境 WSADATA WSAData; if(WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { printf("初始化 Socket环境失败"); return -1; }
-
建立连接
// 创建 Client 套接字 SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == client) { perror("创建 Client Socket失败!\n"); return -1; } // 创建并初始化代表服务器地址的IP和端口 char IP[] = "127.0.0.1"; int PORT = 8000; struct sockaddr_in server_addr; // 服务器IP和端口信息 server_addr.sin_family = AF_INET, // 协议为网络协议 server_addr.sin_port = htons(PORT), // 绑定的端口 // 绑定IP地址 server_addr.sin_addr.S_un.S_addr = inet_addr(IP); // 连接上面服务器地址信息指定的服务器 connect(client, (SOCKADDR*)&server_addr, sizeof(server_addr));
-
与服务器进行交互
// 处理客户端间的连接 char buf[124] = {0}; send(client, buf, sizeof(buf), 0); // 发送数据 recv(client, buf, sizeof(buf), 0); // 接收数据 printf("Client 接收到的数据为:%s\n", buf);
-
断块连接、释放环境
// 关闭连接并释放资源 closesocket(client); WSACleanup();
五、运行结果与源码
-
服务器
#include<stdio.h> #include<winsock2.h> int main () { // 初始化 Socket环境 WSADATA WSAData; if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { perror("初始化 Socket环境失败\n"); return -1; } // 创建 Server 套接字 SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == server) { perror("创建 Server Socket失败!\n"); return -1; } // 创建并初始化服务器需要绑定IP和端口 char IP[] = "127.0.0.1"; // 该ip代码的是本机地址 int PORT = 8000; struct sockaddr_in server_addr; // 服务器IP和端口信息 server_addr.sin_family = AF_INET, // 协议为网络协议 server_addr.sin_port = htons(PORT), // 绑定的端口 // 绑定IP地址 server_addr.sin_addr.S_un.S_addr = inet_addr(IP); // 服务器套接字绑定ip和端口 int StatusCode = bind(server, (SOCKADDR*)&server_addr, sizeof(server_addr)); if (SOCKET_ERROR == StatusCode) { perror("Server Socket 绑定IP、端口失败\n"); return -1; } // 开始监听连接, 最多等待的连接数设置为10 listen(server, 10); printf("Server 正在 %s %d 监听连接......\n", IP, PORT); // 接收客户端连接 struct sockaddr_in client_addr; int client_addrlen = sizeof(client_addr); SOCKET client = accept(server, (SOCKADDR*)&client_addr, &client_addrlen); if (SOCKET_ERROR == client) { perror("连接客户端失败\n"); } // 处理客户端间的连接 char buf[124] = {0}; recv(client, buf, sizeof(buf), 0); // 接收数据 send(client, buf, sizeof(buf), 0); // 发送数据 // 关闭连接 closesocket(client); closesocket(server); // 释放资源 WSACleanup(); return 0; }
-
客户端
#include<stdio.h> #include<winsock2.h> int main () { // 初始化 Socket环境 WSADATA WSAData; if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { perror("初始化 Socket环境失败\n"); return -1; } // 创建 Client 套接字 SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == client) { perror("创建 Client Socket失败!\n"); return -1; } // 创建并初始化代表服务器地址的IP和端口 char IP[] = "127.0.0.1"; int PORT = 8000; struct sockaddr_in server_addr; // 服务器IP和端口信息 server_addr.sin_family = AF_INET, // 协议为网络协议 server_addr.sin_port = htons(PORT), // 绑定的端口 // 绑定IP地址 server_addr.sin_addr.S_un.S_addr = inet_addr(IP); // 连接上面服务器地址信息指定的服务器 connect(client, (SOCKADDR*)&server_addr, sizeof(server_addr)); // 处理客户端间的连接 char buf[124] = {0}; send(client, buf, sizeof(buf), 0); // 发送数据 recv(client, buf, sizeof(buf), 0); // 接收数据 printf("Client 接收到的数据为:%s\n", buf); // 关闭连接并释放资源 closesocket(client); WSACleanup(); return 0; }
-
运行结果
WinSocket常用函数介绍:灰信网