jelasin 的学生作业:
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 8080
#define BACKLOG 10
#define BUFFER_SIZE 1024
// 客户端信息结构体
typedef struct {
int client_socket;
struct sockaddr_in client_addr;
} client_info_t;
// 线程处理函数:处理单个客户端连接
void* handle_client(void* arg) {
client_info_t* client_info = (client_info_t*)arg;
int client_socket = client_info->client_socket;
struct sockaddr_in client_addr = client_info->client_addr;
printf("[线程 %ld] 开始处理客户端: %s:%d\n",
pthread_self(),
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
char buffer[BUFFER_SIZE];
ssize_t bytes_received;
// 与客户端通信循环
while (1) {
bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
printf("[线程 %ld] 收到消息: %s", pthread_self(), buffer);
// 简单回显 - 增加响应缓冲区大小以避免截断警告
char response[BUFFER_SIZE + 64]; // 为格式化字符串预留额外空间
snprintf(response, sizeof(response), "[线程 %ld] Echo: %s", pthread_self(), buffer);
send(client_socket, response, strlen(response), 0);
} else if (bytes_received == 0) {
printf("[线程 %ld] 客户端断开连接: %s:%d\n",
pthread_self(),
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
break;
} else {
perror("recv失败");
break;
}
}
close(client_socket);
free(client_info);
printf("[线程 %ld] 客户端处理完成,线程退出\n", pthread_self());
pthread_exit(NULL);
}
// 函数:创建和绑定服务器socket
int create_and_bind_server(const char* ip, int port) {
int server_socket;
struct sockaddr_in server_addr;
int reuse = 1;
// 1. 创建套接字
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("socket创建失败");
return -1;
}
printf("Socket创建成功 (fd: %d)\n", server_socket);
// 设置SO_REUSEADDR选项
if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
perror("setsockopt失败");
close(server_socket);
return -1;
}
// 2. 配置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
// 根据IP参数设置绑定地址
if (ip == NULL || strcmp(ip, "0.0.0.0") == 0) {
server_addr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有可用接口
printf("配置为监听所有接口 (0.0.0.0:%d)\n", port);
} else {
if (inet_aton(ip, &server_addr.sin_addr) == 0) {
printf("无效的IP地址: %s\n", ip);
close(server_socket);
return -1;
}
printf("配置为监听指定IP (%s:%d)\n", ip, port);
}
// 3. 绑定IP地址和端口号
if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("bind失败");
close(server_socket);
return -1;
}
printf("成功绑定到端口 %d\n", port);
return server_socket;
}
int main(int argc, char *argv[]) {
int server_socket;
// 解析命令行参数
char *server_ip = NULL;
int server_port = SERVER_PORT;
if (argc >= 2) {
server_port = atoi(argv[1]);
if (server_port 65535) {
printf("无效端口号: %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}
if (argc >= 3) {
server_ip = argv[2];
}
// 创建和绑定服务器socket
server_socket = create_and_bind_server(server_ip, server_port);
if (server_socket == -1) {
exit(EXIT_FAILURE);
}
// 4. 开始监听
if (listen(server_socket, BACKLOG) == -1) {
perror("listen失败");
close(server_socket);
exit(EXIT_FAILURE);
}
printf("服务器开始监听,等待客户端连接...\n");
printf("监听队列大小: %d (最多可同时等待 %d 个连接)\n", BACKLOG, BACKLOG);
printf("服务器地址: %s:%d\n", server_ip ? server_ip : "0.0.0.0", server_port);
// 5. 主循环:接受客户端连接
while (1) {
printf("\n等待新的客户端连接...\n");
// 接受客户端连接
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_len);
if (client_socket == -1) {
perror("accept失败");
continue;
}
printf("客户端连接成功: %s:%d (socket fd: %d)\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port),
client_socket);
// 创建结构体保存客户端信息
client_info_t* client_info = (client_info_t*)malloc(sizeof(client_info_t));
if (client_info == NULL) {
perror("malloc失败");
close(client_socket);
continue;
}
client_info->client_socket = client_socket;
client_info->client_addr = client_addr;
// 创建线程处理客户端连接
pthread_t tid;
if (pthread_create(&tid, NULL, handle_client, client_info) != 0) {
perror("pthread_create失败");
close(client_socket);
free(client_info);
} else {
// 分离线程,在线程结束时自动回收资源
pthread_detach(tid);
printf("为客户端 %s:%d 创建处理线程 %ld\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port),
tid);
}
}
close(server_socket);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024
int main() {
int client_socket;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE];
ssize_t bytes_received;
// 创建套接字
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == -1) {
perror("socket创建失败");
exit(EXIT_FAILURE);
}
// 配置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
// 连接到服务器
if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("连接服务器失败");
close(client_socket);
exit(EXIT_FAILURE);
}
printf("成功连接到服务器 %s:%d\n", SERVER_IP, SERVER_PORT);
printf("输入消息发送到服务器 (输入'quit'退出):\n");
while (1) {
// 从用户获取输入
printf("客户端> ");
fflush(stdout);
if (fgets(buffer, BUFFER_SIZE, stdin) == NULL) {
break;
}
// 检查退出条件
if (strncmp(buffer, "quit", 4) == 0) {
printf("客户端退出...\n");
break;
}
// 发送消息到服务器
ssize_t bytes_sent = send(client_socket, buffer, strlen(buffer), 0);
if (bytes_sent == -1) {
perror("发送消息失败");
break;
}
// 接收服务器响应
bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
// 移除消息末尾的换行符(如果有的话)
char *newline = strchr(buffer, '\n');
if (newline) *newline = '\0';
printf("服务器响应: %s\n", buffer);
} else if (bytes_received == 0) {
printf("服务器关闭了连接\n");
break;
} else {
perror("接收消息失败");
break;
}
}
// 关闭套接字
close(client_socket);
return 0;
}