C语言完成Socket通信
一.服务端实现
//
// Created by wyd on 2025/11/1.
//#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <unistd.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {WSADATA wsa_data;int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);if (result != 0) {printf("WSAStartup failed: %d", result);return 1;}// 1. 创建Socket(TCP,IPv4)SOCKET server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (server_fd == INVALID_SOCKET) {printf("socket failed: %d", WSAGetLastError());WSACleanup();return 1;}// 2. 绑定地址struct sockaddr_in address;address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡address.sin_port = htons(PORT); // 端口转网络字节序if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) == SOCKET_ERROR) {printf("bind failed: %d", WSAGetLastError());closesocket(server_fd);WSACleanup();return 1;}// 3. 监听连接if (listen(server_fd, 5) == SOCKET_ERROR) {printf("listen failed: %d", WSAGetLastError());closesocket(server_fd);WSACleanup();return 1;}printf("Server listening on port %d...", PORT);// 4. 接受客户端连接struct sockaddr_in client_addr;int client_addr_len = sizeof(client_addr);SOCKET new_socket = accept(server_fd, (struct sockaddr*)&client_addr, &client_addr_len);if (new_socket == INVALID_SOCKET) {printf("accept failed: %d", WSAGetLastError());closesocket(server_fd);WSACleanup();return 1;}printf("Client connected.\n");// 5. 与客户端通信char buffer[BUFFER_SIZE];while (1) {// 接收数据int bytes_received = recv(new_socket, buffer, BUFFER_SIZE - 1, 0);if (bytes_received > 0) {buffer[bytes_received] = '\0'; // 确保字符串以 NULL 结尾printf("Received: %s\n", buffer);// 发送响应const char* response = "Hello from server!";send(new_socket, response, strlen(response), 0);} else if (bytes_received == 0) {printf("Client disconnected.\n");break;} else {printf("recv failed: %d\n", WSAGetLastError());break;}}// 6. 清理资源closesocket(new_socket);closesocket(server_fd);WSACleanup();return 0;
}
二.客户端实现
//
// Created by wyd on 2025/11/1.
//#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <string.h>#define PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024int main() {// 初始化WSADATA wsa_data;int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);// 初始化失败,初始化失败则退出程序if (result != 0){printf("WSAStartup failed: %d", result);return 1;}// 1. 创建SocketSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock == INVALID_SOCKET){printf("socket failed: %d", WSAGetLastError());WSACleanup();return 1;}// 2. 配置服务端地址struct sockaddr_in serv_addr;serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // 使用 inet_addr 转换 IP 地址// 3. 连接服务端if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR){printf("connect failed: %d", WSAGetLastError());closesocket(sock);WSACleanup();return 1;}printf("Connected to server: %s:%d", SERVER_IP, PORT);// 4. 与服务器通信char buffer[BUFFER_SIZE];while (1) {// 输入消息printf("Enter message: ");fgets(buffer, BUFFER_SIZE, stdin);buffer[strcspn(buffer, "\n")] = '\0'; // 去掉换行符// 发送消息send(sock, buffer, strlen(buffer), 0);// 接收响应int bytes_received = recv(sock, buffer, BUFFER_SIZE - 1, 0);if (bytes_received > 0) {buffer[bytes_received] = '\0';printf("Server response: %s\n", buffer);} else if (bytes_received == 0) {printf("Server disconnected.\n");break;} else {printf("recv failed: %d\n", WSAGetLastError());break;}}// 5. 清理资源closesocket(sock);WSACleanup();return 0;
}
三.编译代码
GCC参数说明:
gcc:调用 GCC 编译器。xxx.c:要编译的源文件。-o xxx.exe:指定生成的目标文件名(可执行文件)。-lws2_32:链接 Winsock 库(ws2_32.lib),这是 Windows 网络编程所必需的。
gcc server.c -o server.exe -lws2_32
gcc client.c -o client.exe -lws2_32
三.监听读取文件的案例
客户端Code
//
// Created by wyd on 2025/11/1.
//#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <string.h>#define PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 4096int main() {// 初始化WSADATA wsa_data;int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);// 初始化失败,初始化失败则退出程序if (result != 0){printf("WSAStartup failed: %d", result);return 1;}// 1. 创建SocketSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock == INVALID_SOCKET){printf("socket failed: %d", WSAGetLastError());WSACleanup();return 1;}// 2. 配置服务端地址struct sockaddr_in serv_addr;serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // 使用 inet_addr 转换 IP 地址// 3. 连接服务端if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR){printf("connect failed: %d", WSAGetLastError());closesocket(sock);WSACleanup();return 1;}printf("Connected to server: %s:%d", SERVER_IP, PORT);FILE* fp = fopen("file_to_send.txt", "rb");if (!fp) {perror("Failed to open file");closesocket(sock);WSACleanup();return 1;}// 4. 与服务器通信char buffer[BUFFER_SIZE];int bytes_read;while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, fp)) > 0) {send(sock, buffer, bytes_read, 0);}fclose(fp);// 5. 清理资源closesocket(sock);WSACleanup();return 0;
}
服务端Code
//
// Created by wyd on 2025/11/1.
//#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <unistd.h>#define PORT 8080
#define BUFFER_SIZE 4096int main() {WSADATA wsa_data;int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);if (result != 0) {printf("WSAStartup failed: %d", result);return 1;}// 1. 创建Socket(TCP,IPv4)SOCKET server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (server_fd == INVALID_SOCKET) {printf("socket failed: %d", WSAGetLastError());WSACleanup();return 1;}// 2. 绑定地址struct sockaddr_in address;address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡address.sin_port = htons(PORT); // 端口转网络字节序if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) == SOCKET_ERROR) {printf("bind failed: %d", WSAGetLastError());closesocket(server_fd);WSACleanup();return 1;}// 3. 监听连接if (listen(server_fd, 5) == SOCKET_ERROR) {printf("listen failed: %d", WSAGetLastError());closesocket(server_fd);WSACleanup();return 1;}printf("Server listening on port %d...", PORT);// 4. 接受客户端连接struct sockaddr_in client_addr;int client_addr_len = sizeof(client_addr);SOCKET new_socket = accept(server_fd, (struct sockaddr*)&client_addr, &client_addr_len);if (new_socket == INVALID_SOCKET) {printf("accept failed: %d", WSAGetLastError());closesocket(server_fd);WSACleanup();return 1;}printf("Client connected.\n");// 5. 与客户端通信char buffer[BUFFER_SIZE];FILE* fp = fopen("received_file.txt","wb");if (!fp){perror("Failed to open file");closesocket(new_socket);WSACleanup();return 1;}while (1) {// 接收数据int bytes_received = recv(new_socket, buffer, BUFFER_SIZE - 1, 0);if (bytes_received > 0) {buffer[bytes_received] = '\0'; // 确保字符串以 NULL 结尾fwrite(buffer, 1, bytes_received, fp);printf("Received: %s\n", buffer);// 发送响应const char* response = "Hello from server!";send(new_socket, response, strlen(response), 0);} else if (bytes_received == 0) {printf("Client disconnected.\n");break;} else {printf("recv failed: %d\n", WSAGetLastError());break;}}fclose(fp);// 6. 清理资源closesocket(new_socket);closesocket(server_fd);WSACleanup();return 0;
}
读取file_to_send.txt文件中的内容,则服务端也会输入内容copy到received_file.txt 完成监听工作
