聊天室c语言程序,socket 多线程聊天室的实现(C语言)

本文介绍如何使用C语言实现一个简单的聊天室程序,包括服务器端和客户端。服务器端能监听并连接多个客户端,接收并广播消息,客户端则能与服务器建立连接,发送和接收消息。通过socket编程,涉及创建套接字、绑定、监听、连接、接收和发送数据等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

人生不止眼前的苟且,代码也不止数据的增删改查,也有有趣的网络编程。如何用C语言做一个简单的服务器和客户端,实现一个聊天室程序呢?这里就简单的写一下博主的实现。

一、程序需求

实现一个简单的服务器,包括以下功能:

可以监听并且与多个客户端建立TCP链接。

可以接收客户端发来的消息,并发送给所有的客户端。

可查询所有的客户端链接。

实现客户端有如下功能:

输入服务器端口号,与服务器端建立链接。

发送消息给服务器。

接收并打印服务器发来的消息。

二、实现分析

借用百度的一张图,这个流程很好的解释了socket编程的根本:

80d38855f874228a980f281a379f8618.png

服务器端的处理流程思路:

创建socket套接字

绑定ip与端口号

创建监听线程,等待客户端链接

接收到一个客户端链接则创建一个线程进行消息接收处理

客户端关闭,关闭相关进程

服务器关闭

客户端的处理流程思路:

创建socket套接字

输入端口号链接服务器

创建线程处理服务器消息

接收控制台输入发送给服务器

客户端关闭

socket的基本api:

三、基本的socket API

### 实现 C 语言基于 Socket聊天室中的私聊功能 为了实现带有私聊功能的聊天室,在服务器端需要维护连接到各个客户端的信息列表。当收到消息时,解析该消息以判断其是否为私聊请求,并根据目标用户名或 ID 将消息转发给特定客户端。 #### 客户端设计 每个客户端启动后向服务器注册自己的身份信息(如昵称)。发送普通广播消息和指定对象的消息格式应有所区别: 对于一般群组消息可以采用如下形式: ``` <msg>hello everyone</msg> ``` 而针对某位用户的私信则可定义成这样: ```xml <pvt to="target_user">secret message</pvt> ``` #### 服务端处理逻辑 每当接收到一条新的输入流数据包时,先检查开头标签来决定下一步动作。如果是 `<pvt>` 开头,则提取 `to` 属性值查找对应在线会话;若是普通的 `<msg>` 则直接分发至所有已登录成员[^1]。 以下是简化版的服务端代码片段用于说明上述机制: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define MAX_CLIENTS 10 #define BUFFER_SIZE 256 typedef struct { int sockfd; char name[BUFFER_SIZE]; } Client; Client clients[MAX_CLIENTS]; // 存储当前活跃客户的结构体数组 int client_count = 0; // 当前活动客户数量计数器 void broadcast_message(const char* msg, const int sender_fd); void private_message(int from_fd, const char* target_name, const char* pvt_msg); // 处理来自某个客户端的新消息 void handle_client_message(int fd) { static char buffer[BUFFER_SIZE]; ssize_t bytes_received = recv(fd, buffer, sizeof(buffer), 0); if (bytes_received <= 0) { close(fd); printf("client disconnected\n"); return ; } buffer[bytes_received] = '\0'; // 解析并响应不同类型的消息 if(strncmp("<pvt",buffer,strlen("<pvt"))==0){ char *start,*end; start=strstr(buffer,"to=\"")+strlen("to=\""); end=strchr(start,'\"'); *end='\0'; char *message= strstr(end+1,">")+1; *(strstr(message,"</pvt>")-1)='\0'; private_message(fd,start,message); } else{ broadcast_message(buffer,fd); } } // 向除自己外的所有其他用户发送公共消息 void broadcast_message(const char* msg, const int sender_fd) { for (size_t i = 0; i < client_count; ++i) { if(clients[i].sockfd != sender_fd && send(clients[i].sockfd,msg,strlen(msg))==-1){ perror("send failed"); } } } // 查找目标用户并向其单独发送私人消息 void private_message(int from_fd, const char* target_name, const char* pvt_msg) { for (size_t i = 0; i < client_count; ++i) { if(strcmp(target_name,clients[i].name)==0){ asprintf(&char *full_msg,"%s whispered:%s",clients[from_fd].name,pvt_msg); send(clients[i].sockfd, full_msg , strlen(full_msg), 0 ); free(full_msg); break; } } } ``` 此示例展示了如何区分不同类型的命令以及相应的处理方式。实际应用中还需要考虑更多细节比如错误检测、超时管理等[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值