C语言网络编程(一对多通讯)

使用C语言实现一个服务器对多个客户端

主要技术除了网络编程几个函数的使用外,还用到了线程,实现方式是一个客户端对应一个新的线程

Server:

#include <pthread.h> // 包含线程库的头文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

void* handle_client(void* arg) {
int client_fd = *(int*)arg; // 从参数中获取客户端套接字文件描述符
char readBuf[128];
char *writeBuf = "I get you!";

while (1) {
sleep(2);//很重要,防止服务器一直连接同一个客户端
// 循环读取客户端发送的每条消息
memset(readBuf, 0, sizeof(readBuf));
int n_read = read(client_fd, readBuf, sizeof(readBuf));
if (n_read > 0) {
// 正常接收到消息
printf("get message from client: %s\n", readBuf);
} else if (n_read == 0) {
// 客户端关闭连接
printf("Client disconnected.\n");
break;
} else {
// 读取失败
perror("read");
break;
}

// 发送消息回客户端
if (write(client_fd, writeBuf, sizeof(writeBuf)) == -1) {
perror("write");
break;
}
}

close(client_fd); // 关闭客户端套接字
pthread_exit(NULL); // 退出线程
}

int main() {
int s_fd, c_fd;
struct sockaddr_in s_addr, c_addr;
socklen_t len;
char readBuf[128];
char *writeBuf = "I get you!";
// 1. 创建socket网络套接字
s_fd = socket(AF_INET, SOCK_STREAM, 0);
if (s_fd == -1) {
perror("socket");
exit(-1);
}

// 2. 绑定本地IP地址和端口号到socket网络套接字上
memset(&s_addr, 0, sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(8421);
inet_aton("192.168.190.141", &s_addr.sin_addr);
if (bind(s_fd, (struct sockaddr*)&s_addr, sizeof(struct sockaddr_in)) == -1) {
perror("bind");
exit(-1);
}

// 3. 将socket套接字变为监听套接字,准备接受客户端的连接
if (listen(s_fd, 10) == -1) {
perror("listen");
exit(-1);
}

// 4. 服务器阻塞等待客户端的连接
len = sizeof(struct sockaddr_in);
// 服务器主循环
while (1) {
// 4. 服务器阻塞等待客户端的连接
len = sizeof(struct sockaddr_in);
c_fd = accept(s_fd, (struct sockaddr*)&c_addr, &len);
if (c_fd == -1) {
perror("accept");
exit(-1);
}
printf("Success Connected\n");
printf("get connect :%s\n", inet_ntoa(c_addr.sin_addr));


 
// 创建新线程处理客户端连接
pthread_t thread_id;
if (pthread_create(&thread_id, NULL, handle_client, &c_fd) != 0) {
perror("pthread_create");
close(c_fd); // 如果线程创建失败,关闭客户端套接字
exit(-1);
}
// 销毁线程,这里不销毁,让线程自然结束
pthread_detach(thread_id);
}

close(s_fd); // 关闭服务器套接字
return 0;
}

Client:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

int main() {
int c_fd;
struct sockaddr_in s_addr;
char msg[128], readBuf[128];

// 1. 创建socket网络套接字
c_fd = socket(AF_INET, SOCK_STREAM, 0);
if (c_fd == -1) {
perror("socket");
exit(-1);
}

// 2. 连接服务端
memset(&s_addr, 0, sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
inet_aton("192.168.190.141", &s_addr.sin_addr);
s_addr.sin_port = htons(8421);

if (connect(c_fd, (struct sockaddr*)&s_addr, sizeof(struct sockaddr_in)) == -1) {
perror("connect");
exit(-1);
}
printf("Connected to server at %s\n", inet_ntoa(s_addr.sin_addr));

// 3. 发送信息到服务端
while (scanf("%127s", msg) == 1) { // 使用%127s防止缓冲区溢出
if (write(c_fd, msg, strlen(msg)) == -1) {
perror("write");
break;
}

// 4. 读取服务端发来的消息
int n_read = read(c_fd, readBuf, sizeof(readBuf));
if (n_read > 0) {
readBuf[n_read] = '\0'; // 确保字符串以null字符结尾
printf("Received message: %s\n", readBuf);
} else if (n_read == -1) {
perror("read");
break;
} else if (n_read == 0) {
printf("Server closed the connection.\n");
break;
}
}

close(c_fd);
return 0;
}
posted @   小犟  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示