Linux C语言 server 端(TCP):
// socketServer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // 提供 close、read 和 write (这里通过 send 间接使用,因为 send 是 write 的一个更高级别的封装)
#include <arpa/inet.h> // 提供了用于网络地址转换的函数声明,如将点分十进制格式的 IP 地址转换为网络字节序,以及将端口号从主机字节序转换为网络字节序。#define PORT 12000 // socket 绑定的端口好
#define BUFFER_SIZE 1024 // 缓存大小int main() {int server_fd, new_socket;struct sockaddr_in address; // 结构体,用于存储 IPv4 地址和端口号的信息。int opt = 1;int addrlen = sizeof(address);char buffer[BUFFER_SIZE] = {0};const char *hello = "Hello from server";// 创建socketif ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {/*AF_INET:指定地址族为 IPv4。SOCK_STREAM:指定套接字类型为 TCP(面向连接的字节流)。0:指定协议为 0,通常对于 SOCK_STREAM 和 AF_INET,这个参数为 0,意味着使用 TCP。*/perror("socket failed");exit(EXIT_FAILURE);}// 绑定socket到端口if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}address.sin_family = AF_INET; // IPv4address.sin_addr.s_addr = INADDR_ANY; // 任何地址address.sin_port = htons(PORT); // 端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 监听连接if (listen(server_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}// 接受连接while (1) {printf("等待连接...\n");if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept");exit(EXIT_FAILURE);}// 接收数据read(new_socket, buffer, BUFFER_SIZE);printf("收到消息: %s\n", buffer);// 发送数据send(new_socket, hello, strlen(hello), 0);printf("欢迎消息已发送\n");// 关闭当前连接close(new_socket);}// 关闭服务器socketclose(server_fd);return 0;
}
编译:gcc 编译器
gcc -o Csocket socketServer.c
运行:
./Csocket
Windows 10 C/C++ client 端使用 TCP 协议:
#include <iostream>
#include <stdlib.h> // 包含 system() 函数
#include <winsock2.h>
#include <ws2tcpip.h> // 包含inet_pton的头文件#pragma comment(lib, "ws2_32.lib") // 链接 Winsock 库#define PORT 12000
#define BUFFER_SIZE 1024int main() {system("chcp 65001"); //在Windows 10及更高版本中, 使用 chcp 65001 设置命令行的字符集为 utf-8WSADATA wsaData;SOCKET sock;struct sockaddr_in server;char buffer[BUFFER_SIZE] = { 0 };const char* message = u8"你好,from client!"; // utf-8 字符串// 初始化Winsockif (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << u8"Failed to initialize Winsock. Error Code: " << WSAGetLastError() << std::endl;return 1;}// 创建Socketif ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {std::cerr << u8"Could not create socket. Error Code: " << WSAGetLastError() << std::endl;WSACleanup();return 1;}// 配置服务器地址结构server.sin_family = AF_INET;server.sin_port = htons(PORT);if (inet_pton(AF_INET, "服务器 IPv4 地址", &server.sin_addr) <= 0) {std::cerr << u8"Invalid address/ Address not supported. Error Code: " << WSAGetLastError() << std::endl;closesocket(sock);WSACleanup();return 1;}// 连接到服务器if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {std::cerr << u8"Connect failed. Error Code: " << WSAGetLastError() << std::endl;closesocket(sock);WSACleanup();return 1;}// 发送数据send(sock, message, strlen(message), 0);std::cout << u8"消息已发送: " << message << std::endl;// 接收服务器的响应int bytes_received = recv(sock, buffer, BUFFER_SIZE - 1, 0); // 保留一个字节给 '\0'if (bytes_received > 0) {buffer[bytes_received] = '\0'; // 确保字符串结束std::cout << u8"收到来自服务器的消息: " << buffer << std::endl;}else {std::cerr << u8"接收数据失败. Error Code: " << WSAGetLastError() << std::endl;}// 关闭Socketclosesocket(sock);WSACleanup();return 0;
}
编译运行:Visual Studio 2022 编译环境:
服务器端:
Linux C++ socket 编程:
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 12000 // 端口
#define BUFFER_SIZE 1024class Server {
public:Server() {server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd < 0) {std::cerr << "Socket creation failed" << std::endl;exit(EXIT_FAILURE);}sockaddr_in address;int addrlen = sizeof(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)) < 0) {std::cerr << "Bind failed" << std::endl;close(server_fd);exit(EXIT_FAILURE);}if (listen(server_fd, 3) < 0) {std::cerr << "Listen failed" << std::endl;close(server_fd);exit(EXIT_FAILURE);}std::cout << "Server is listening on port " << PORT << std::endl;}~Server() {close(server_fd);}void acceptConnection() {sockaddr_in address;int addrlen = sizeof(address);int new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);if (new_socket < 0) {std::cerr << "Accept failed" << std::endl;return;}char buffer[BUFFER_SIZE];int valread = read(new_socket, buffer, BUFFER_SIZE);std::cout << "Message from client: " << buffer << std::endl;const char *response = "Hello from server";send(new_socket, response, strlen(response), 0);std::cout << "Response sent to client" << std::endl;close(new_socket);}private:int server_fd;
};int main() {Server server;while (true) {server.acceptConnection();}return 0;
}
编译:g++ 编译器
g++ -o socket socketServer.cpp
运行:
./socket
Windows Client 端:
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string> #pragma comment(lib, "Ws2_32.lib") #define PORT 12000
#define BUFFER_SIZE 1024 int main() {// 初始化Winsock WSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {std::cerr << "WSAStartup failed: " << iResult << std::endl;return 1;}// 创建套接字 SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (clientSocket == INVALID_SOCKET) {std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;WSACleanup();return 1;}// 设置服务器地址和端口 sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(PORT);// 将服务器地址从文本转换为二进制形式 in_addr serverIP;if (inet_pton(AF_INET, "服务器端 IPv4 地址", &serverIP) <= 0) {std::cerr << "Invalid address/ Address not supported" << std::endl;closesocket(clientSocket);WSACleanup();return 1;}memcpy(&(serverAddr.sin_addr), &serverIP, sizeof(serverIP)); // 连接到服务器 iResult = connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));if (iResult == SOCKET_ERROR) {std::cerr << "Error at connect(): " << WSAGetLastError() << std::endl;closesocket(clientSocket);WSACleanup();return 1;}std::cout << "Connected to server" << std::endl;// 发送消息到服务器 const char* sendbuf = "Hello from Windows client";send(clientSocket, sendbuf, strlen(sendbuf), 0);std::cout << "Message sent to server" << std::endl;// 接收来自服务器的响应 char recvbuf[BUFFER_SIZE] = { 0 };int iRecvResult = recv(clientSocket, recvbuf, BUFFER_SIZE, 0);if (iRecvResult > 0)std::cout << "Message from server: " << recvbuf << std::endl;else {std::cerr << "recv failed: " << WSAGetLastError() << std::endl;}// 关闭套接字 closesocket(clientSocket);// 清理Winsock WSACleanup();return 0;
}
socket 简易 HTTP/1.1 请求
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>
#include <stdlib.h>#pragma comment(lib, "Ws2_32.lib")#define PORT 8080 // Http 8080 端口
#define BUFFER_SIZE 50000 // 缓存大小int main() {system("chcp 65001"); // 设置命令行 utf-8 字符集,适用于 win10 及以上的系统// 初始化Winsock WSADATA wsaData;int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);if (iResult != 0) {std::cerr << "WSAStartup failed: " << iResult << std::endl;return 1;}// 创建套接字 SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (clientSocket == INVALID_SOCKET) {std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;WSACleanup();return 1;}// 设置服务器地址和端口 sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(PORT);// 将服务器地址从文本转换为二进制形式 in_addr serverIP;if (inet_pton(AF_INET, "此字符串修改填充为服务器 IPv4 地址", &serverIP) <= 0) {std::cerr << "Invalid address/ Address not supported" << std::endl;closesocket(clientSocket);WSACleanup();return 1;}memcpy(&(serverAddr.sin_addr), &serverIP, sizeof(serverIP));// 连接到服务器 iResult = connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));if (iResult == SOCKET_ERROR) {std::cerr << "Error at connect(): " << WSAGetLastError() << std::endl;closesocket(clientSocket);WSACleanup();return 1;}std::cout << "Connected to server" << std::endl;// 发送消息到服务器 const char* sendbuf = u8"GET /path HTTP/1.1\r\nHost: [修改为服务器主机名]\r\nAccept: */*\r\nConnection: close\r\n\r\n"; // http 请求报文。 path 修改为请求资源的路径send(clientSocket, sendbuf, strlen(sendbuf), 0);std::cout << "Message sent to server: \n" << sendbuf << std::endl;// 接收来自服务器的响应 char recvbuf[BUFFER_SIZE] = { 0 };std::string fullResponse; // 用于存储完整的响应while (true) { // 分块传输,接受完整的数据(拼接每次接受的 chunk)int iRecvResult = recv(clientSocket, recvbuf, BUFFER_SIZE - 1, 0);if (iRecvResult > 0) {recvbuf[iRecvResult] = '\0'; // 确保字符串结束fullResponse += recvbuf; // 将接收到的数据添加到完整响应中}else if (iRecvResult == 0) {// 连接关闭break;}else {std::cerr << "recv failed: " << WSAGetLastError() << std::endl;break;}}std::cout << "Message from server: " << fullResponse << std::endl;// 关闭套接字 closesocket(clientSocket);// 清理Winsock WSACleanup();return 0;
}
以上代码可以拿来做测试,只能向支持 HTTP/1.1 的服务器发起请求,且不支持 HTTPS(需要SSL/TLS 握手)。
编译运行:环境 Visual Studio 2022。
请求一个 tomcat 服务器的默认 html 页面: