Linux 嵌入式 C 实现简单的网络聊天室服务端

Linux 嵌入式 C 实现简单的网络聊天室

版权声明:https://blog.csdn.net/qq_39603089/article/details/85327599

客户端:https://blog.csdn.net/qq_39603089/article/details/85328262

下载地址在最下面

使用C/S 模式,参考下图:

在这里插入图片描述

服务端系统简单流程图

Linux 嵌入式 C 实现简单的网络聊天室服务端_第1张图片

思路如下:

  1. 运行服务端,绑定端口IP,并开始监听连接。

  2. signal(); 函数捕捉退出信号量,用自定义函数处理,函数功能,向所有在线用户发送结束命令,等待2秒后退出。

  3. 进入循环阻塞等待用户连接。并使用pv信号量做用户上限控制。

  4. 消费信号量,用户建立连接后等待接收用户昵称。

  5. 查找在线用户昵称是否重复,如果重复向用户发送提醒,并是否pv信号量。

  6. 如果不重复,为用户建立线程来监听该用户发送的消息。

  7. 线程处理用户消息并为其转发。

  8. 用户退出后,断开与用户的连接。并释放pv 信号量。

  9. pv 消耗完时,服务端就会进入阻塞状况,直到用用户退出释放pv 信号量。

  10. 当有pv 信号是就循环从用户结构体数组里找可用的结构体资源。

部分代码解释

#define THREAD_NUMBER 30 //最大链接数
struct Users{            
	char name[50];
	pthread_t thread;
	char buf[BUFFER_SIZE];
	int client_fd;
	char address[20];
	int login;         //0表示这个结构体为被使用  1 表示这个结构体已经有用户使用
}users[THREAD_NUMBER];    // 结构体数组的长度与pv信号量相等。
init_sem(sem_id, THREAD_NUMBER); //有pv资源时就一定可以找到没有使用的结构体

结构体内保存了用户信息

signal(SIGINT, my_func);
signal(SIGQUIT, my_func);
signal(SIGTSTP,my_func);

使用my_func函数来处理三个退出信号 my_func 实现的功能就是向用户发送退出消息。

sem_p(sem_id);
while(i<THREAD_NUMBER){                 //遍历列表
	if(users[i].login==0)               //找到可用资源  0 表示可用  1 不可用
	break;
	i++;
	if(i==THREAD_NUMBER){              //循环查找
	i=0;	
	}
}

使结构体数组可以循环使用

users[i].client_fd = accept(sockfd,(struct sockaddr*)&client_sockaddr, &sin_size)

等待接收用户连接

recvbytes=recv(users[i].client_fd, users[i].name, BUFFER_SIZE, 0)

接收用户发送来的消息,也就是用户的昵称,用于之后的判断是否重复。

res = pthread_create(&users[i].thread, NULL, thrd_func, (void*)i);

为用户建立线程函数。专门做该用户的发送消息的监听,大多数情况下处于阻塞监听状态。并实现对用户消息的转发。

在线程内部

if ((recvbytes = recv(users[i].client_fd, users[i].buf, BUFFER_SIZE, 0)) <= 0)
………………
strdeal(users[i].buf,users[i].name);  //处理消息函数

循环阻塞监听接收信息。成功后处理消息然后发送。

void strdeal(char s[],char se_name[]){  
………………
for(i;i<strlen(s);i++){
	if(n>2){
		buf[j]=s[i];
		j++;	
	}else if(n==2){
		if(len==0){
		n++;
		name[j]='\0';
		j=0;
		i--;
		continue;
		}
		name[j]=s[i];
		j++;
		len--;
	}else if(n==1){
		if(s[i]==':'){
		n++;
		name[j]='\0';
		len = atoi(name);
		j=0;
		continue;
	}
	name[j]=s[i];
	j++;
	}else{
		if(s[i]==':'){
		n++;
		sign[j]='\0';
	j=0;
	continue;
}
sign[j]=s[i];
j++;
}	
}
if(strcmp(sign,"All")==0){
………………//发送给所有在线人
}else{
………………//发送给单个用户
}
}

处理接收后的字符串。

如果是以All::str开头,则转发给在线的所有用户。str是用户群发内容

如果是以User:len:strlen是用户发送消息目标用户的昵称长度。str是目标昵称和发送内容的拼接

拼接处理在客户端进行。

详情,请参照源代码学习。

客户端:

https://download.csdn.net/download/qq_39603089/10881918

服务端:

https://download.csdn.net/download/qq_39603089/10881905

你可能感兴趣的:(嵌入式)