#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>#define MAX_CLIENTS 2 // 最大客户端连接数
#define BUFFER_SIZE 1024 // 消息缓冲区大小int main(int argc, char *argv[]) {/* 参数校验 */if (argc != 2) {printf("用法: %s <端口号>\n", argv[0]);exit(1);}/* 创建服务器socket */// AF_INET: IPv4协议// SOCK_STREAM: 流式socket(TCP)int server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd < 0) {perror("socket创建失败");exit(1);}/* 配置服务器地址 */struct sockaddr_in addr = {.sin_family = AF_INET, // IPv4地址族.sin_port = htons(atoi(argv[1])), // 端口号(主机字节序转网络字节序).sin_addr.s_addr = INADDR_ANY // 监听所有本地接口};/* 绑定socket到指定地址 */if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) {perror("绑定失败");close(server_fd);exit(1);}/* 开始监听连接请求 */// 参数5: 等待连接队列的最大长度if (listen(server_fd, 5) < 0) {perror("监听失败");close(server_fd);exit(1);}printf("服务器已启动,监听端口: %s\n", argv[1]);/* 客户端管理数据结构 */int client_sockets[MAX_CLIENTS] = {0}; // 客户端socket数组char client_ids[MAX_CLIENTS] = {0}; // 客户端标识符('1'或'2')fd_set readfds; // 文件描述符集合int max_fd; // 最大文件描述符值/* 主事件循环 */while(1) {// 清空文件描述符集合FD_ZERO(&readfds);// 添加服务器socket到监听集合FD_SET(server_fd, &readfds);max_fd = server_fd;// 添加客户端socket到监听集合for(int i = 0; i < MAX_CLIENTS; i++) {if(client_sockets[i] > 0) {FD_SET(client_sockets[i], &readfds);if(client_sockets[i] > max_fd)max_fd = client_sockets[i];}}/* 使用select监听IO事件 */// 参数说明:// 1. max_fd+1: 最大文件描述符值+1// 2. &readfds: 读事件监听集合// 3. NULL: 不监听写事件// 4. NULL: 不监听异常事件// 5. NULL: 无限等待int activity = select(max_fd + 1, &readfds, NULL, NULL, NULL);if ((activity < 0) && (errno != EINTR)) {perror("select错误");}/* 处理新连接请求 */if (FD_ISSET(server_fd, &readfds)) {// 接受新连接int new_socket = accept(server_fd, NULL, NULL);if (new_socket < 0) {perror("接受连接失败");continue;}// 将新客户端添加到数组int added = 0;for(int i = 0; i < MAX_CLIENTS; i++) {if(client_sockets[i] == 0) {client_sockets[i] = new_socket;// 接收客户端标识符(阻塞式接收第一个字节)recv(new_socket, &client_ids[i], 1, 0);printf("客户端 %c 已连接\n", client_ids[i]);added = 1;break;}}if (!added) {printf("连接已满,拒绝新连接\n");close(new_socket);}}/* 处理客户端消息 */for(int i = 0; i < MAX_CLIENTS; i++) {int sd = client_sockets[i];if (sd > 0 && FD_ISSET(sd, &readfds)) {char buffer[BUFFER_SIZE] = {0};// 接收消息int valread = read(sd, buffer, BUFFER_SIZE);/* 处理断开连接 */if (valread == 0) {getpeername(sd, (struct sockaddr*)&addr, (socklen_t*)&addr);printf("客户端 %c 断开连接\n", client_ids[i]);close(sd);client_sockets[i] = 0;client_ids[i] = 0;}/* 转发消息 */else {printf("转发来自客户端 %c 的消息\n", client_ids[i]);// 遍历所有客户端进行转发for(int j = 0; j < MAX_CLIENTS; j++) {int dest = client_sockets[j];// 跳过自身和无效socketif (dest > 0 && client_ids[j] != client_ids[i]) {send(dest, buffer, strlen(buffer), 0);}}}}}}close(server_fd);return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>#define BUFFER_SIZE 1024 // 输入缓冲区大小int main(int argc, char *argv[]) {/* 参数校验 */if (argc != 3) {printf("用法: %s <IP地址> <端口号>\n", argv[0]);exit(1);}/* 创建客户端socket */int sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0) {perror("socket创建失败");exit(1);}/* 配置服务器地址 */struct sockaddr_in serv_addr = {.sin_family = AF_INET,.sin_port = htons(atoi(argv[2])), // 端口号转换.sin_addr.s_addr = inet_addr(argv[1]) // IP地址转换};/* 建立连接 */if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {perror("连接失败");close(sock);exit(1);}/* 发送客户端标识符 */char client_id = '1';send(sock, &client_id, 1, 0);printf("已连接到服务器\n");/* 配置poll监听结构体 */struct pollfd fds[2] = {{.fd = STDIN_FILENO, .events = POLLIN}, // 监听标准输入{.fd = sock, .events = POLLIN} // 监听socket输入};/* 主循环 */while(1) {// 使用poll等待事件(无限等待)int ret = poll(fds, 2, -1);if (ret == -1) {perror("poll错误");break;}/* 处理键盘输入事件 */if (fds[0].revents & POLLIN) {char buffer[BUFFER_SIZE];// 安全获取输入(自动截断)if (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {// 发送消息到服务器send(sock, buffer, strlen(buffer), 0);}}/* 处理服务器消息事件 */if (fds[1].revents & POLLIN) {char buffer[BUFFER_SIZE] = {0};int len = recv(sock, buffer, BUFFER_SIZE, 0);if (len > 0) {printf("收到消息: %s", buffer);} else if (len == 0) {printf("服务器断开连接\n");break;} else {perror("接收错误");break;}}}close(sock);return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>#define BUFFER_SIZE 1024// 全局socket描述符
int sock;
// 互斥锁(保护socket操作)
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;/* 发送线程函数 */
void* send_thread(void* arg) {while(1) {char buffer[BUFFER_SIZE];// 获取用户输入if (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {// 加锁发送pthread_mutex_lock(&lock);send(sock, buffer, strlen(buffer), 0);pthread_mutex_unlock(&lock);}}return NULL;
}/* 接收线程函数 */
void* recv_thread(void* arg) {while(1) {char buffer[BUFFER_SIZE] = {0};int len;// 加锁接收pthread_mutex_lock(&lock);len = recv(sock, buffer, BUFFER_SIZE, 0);pthread_mutex_unlock(&lock);if (len > 0) {printf("收到消息: %s", buffer);} else if (len == 0) {printf("服务器断开连接\n");break;} else {perror("接收错误");break;}}return NULL;
}int main(int argc, char *argv[]) {/* 参数校验 */if (argc != 3) {printf("用法: %s <IP地址> <端口号>\n", argv[0]);exit(1);}/* 创建客户端socket */sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0) {perror("socket创建失败");exit(1);}/* 配置服务器地址 */struct sockaddr_in serv_addr = {.sin_family = AF_INET,.sin_port = htons(atoi(argv[2])),.sin_addr.s_addr = inet_addr(argv[1])};
/* 为服务器准备ip和port(提前)struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr("192.168.110.223");
*//* 建立连接 */if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {perror("连接失败");close(sock);exit(1);}/* 发送客户端标识符 */char client_id = '2';send(sock, &client_id, 1, 0);printf("已连接到服务器\n");/* 创建发送和接收线程 */pthread_t tid_send, tid_recv;pthread_create(&tid_send, NULL, send_thread, NULL);pthread_create(&tid_recv, NULL, recv_thread, NULL);/* 等待线程结束(实际不会执行到这里) */pthread_join(tid_send, NULL);pthread_join(tid_recv, NULL);close(sock);return 0;
}
