面试题答案
一键面试服务器端基本步骤
- 创建套接字:使用
socket
函数创建一个套接字,指定协议族为AF_INET
(IPv4),套接字类型为SOCK_STREAM
(TCP)。 - 绑定地址:使用
bind
函数将套接字与本地地址和端口号绑定。 - 监听连接:使用
listen
函数将套接字设置为监听模式,等待客户端连接。 - 接受连接:使用
accept
函数接受客户端的连接请求,返回一个新的套接字用于与客户端通信。 - 数据传输:使用
send
和recv
函数在新的套接字上进行数据传输。 - 关闭套接字:通信结束后,使用
close
函数关闭套接字。
服务器端关键代码片段
#include <iostream>
#include <winsock2.h> // Windows下需要包含此头文件,Linux下为<sys/socket.h>等
#pragma comment(lib, "ws2_32.lib") // Windows下链接ws2_32库
int main() {
// 初始化Winsock(Windows下)
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 创建套接字
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listenSocket == INVALID_SOCKET) {
std::cerr << "Socket creation failed" << std::endl;
return 1;
}
// 绑定地址
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345); // 端口号
serverAddr.sin_addr.s_addr = INADDR_ANY;
if (bind(listenSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Bind failed" << std::endl;
closesocket(listenSocket);
WSACleanup();
return 1;
}
// 监听连接
if (listen(listenSocket, 5) == SOCKET_ERROR) {
std::cerr << "Listen failed" << std::endl;
closesocket(listenSocket);
WSACleanup();
return 1;
}
std::cout << "Waiting for a connection..." << std::endl;
// 接受连接
sockaddr_in clientAddr;
int clientAddrLen = sizeof(clientAddr);
SOCKET clientSocket = accept(listenSocket, (sockaddr*)&clientAddr, &clientAddrLen);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Accept failed" << std::endl;
closesocket(listenSocket);
WSACleanup();
return 1;
}
// 数据传输
char buffer[1024];
int bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
if (bytesReceived > 0) {
buffer[bytesReceived] = '\0';
std::cout << "Received: " << buffer << std::endl;
}
const char* response = "Message received successfully";
send(clientSocket, response, strlen(response), 0);
// 关闭套接字
closesocket(clientSocket);
closesocket(listenSocket);
WSACleanup();
return 0;
}
客户端基本步骤
- 创建套接字:同服务器端,使用
socket
函数创建一个套接字。 - 连接服务器:使用
connect
函数连接到服务器的地址和端口。 - 数据传输:使用
send
和recv
函数进行数据传输。 - 关闭套接字:通信结束后,关闭套接字。
客户端关键代码片段
#include <iostream>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
int main() {
// 初始化Winsock
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 创建套接字
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Socket creation failed" << std::endl;
return 1;
}
// 连接服务器
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345);
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); // 服务器IP地址
if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Connect failed" << std::endl;
closesocket(clientSocket);
WSACleanup();
return 1;
}
// 数据传输
const char* message = "Hello, server!";
send(clientSocket, message, strlen(message), 0);
char buffer[1024];
int bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
if (bytesReceived > 0) {
buffer[bytesReceived] = '\0';
std::cout << "Received: " << buffer << std::endl;
}
// 关闭套接字
closesocket(clientSocket);
WSACleanup();
return 0;
}
请注意,上述代码在Windows环境下编写,使用了Windows Sockets(Winsock)API。在Linux环境下,需要修改头文件和部分函数名(如 closesocket
改为 close
,WSAStartup
和 WSACleanup
等函数不存在),并且链接不同的库。同时,实际应用中还需要更多的错误处理和优化。