2024年网络编程:json多客户端服务器实现_多客户端网络服务器实现,阿里P8C C++架构师谈

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

//初始化客户端信息结构体数组
memset(cinfo, 0, sizeof(cinfo));//所有数据都清零

//主线程只负责接受客户端链接,不收发数据->收发数据在线程中实现
while(1)
{
	int clientfd = accept(sockfd, (struct sockaddr\*)&clientaddr, &len);
	if(clientfd < 0)
	{
		perror("accept error");
		return -1;
	}

	//创建一个线程
	pthread_t id = 0;
	pthread\_create(&id, NULL, client_thread, (void \*)&clientfd);
	//分离线程
	pthread\_detach(id);

	//把客户端套接字描述符保存(链表, 数组)
	//把套接字保存在最小未使用的数组元素中
	for(int i=0; i<MAXSIZE; i++)
	{
		if(cinfo[i].sockfd == 0)
		{
			cinfo[i].sockfd = clientfd;//保存客户端套接字
			break;
		}
	}
	//获取信号量资源
	sem\_wait(&sm);//目的是等待->线程执行完int clientfd = \*((int \*)arg)这句再循环上面的内容
}

sem\_destroy(&sm);//销毁信号量
//关闭套接字
close(sockfd);
return 0;

}

/*
json数据格式:通用
作用:解析{“id”:“99999”, “to”:“88888”, data:“hello world”}此对象
这对象的99999/888888/helloworld等字符串
(用字符串方法解析比较麻烦)
*/
bool parse_data(char *srcData, char *fromid, char *toid, char *data)
{
//字符串转cjson对象
cJSON *root = cJSON_Parse(srcData);
if(root == NULL) return false;
//解析to
cJSON *toObj = cJSON_GetObjectItem(root,“to”); //根据键获取对应的值
printf(“toId:%s\n”, toObj->valuestring);
sprintf(toid, “%s”, toObj->valuestring);

//解析id
cJSON \*idObj = cJSON\_GetObjectItem(root,"id"); //根据键获取对应的值
printf("Id:%s\n", idObj->valuestring);
sprintf(fromid,"%s", idObj->valuestring);
//解析to
cJSON \*dataObj = cJSON\_GetObjectItem(root,"data"); //根据键获取对应的值
printf("data:%s\n", dataObj->valuestring);
sprintf(data, "%s", dataObj->valuestring);
cJSON\_Delete(root);//释放
return true;

}

//线程-收发数据
void *client_thread(void *arg)
{
int clientfd = *((int *)arg); //传套接字过来,再转int型
//释放信号量资源
sem_post(&sm);
char recvbuffer[1024]={0};
char fromid[16]; //保存发送方id
char toid[16]; //保存接收方id
char data[128];//要发送的数据
while(1)
{
//第一次读取时候给服务器上报id(登录)->存起来和套接字绑定在一起
//{“id”:“99999”, “to”:“88888”, data:“hello world”};
int ret = read(clientfd, recvbuffer, 1024);
if(ret <= 0)
{
printf(“客户端%d掉线\n”, clientfd);
//把链表或数组中的套接字描述符要清理
break;
}

	//解析
	parse\_data(recvbuffer, fromid, toid, data);



	//注册或者登陆要获取套接字里的id信息->从数组中查到套接字,所以对应的id
	//当第一次链接的时候id不存在要自己添加
	for(int i=0; i<MAXSIZE; i++)
	{
		if(cinfo[i].sockfd == clientfd && strlen(cinfo[i].id)==0)
		{
			strcpy(cinfo[i].id, fromid);
			
			//发送反馈信息{type:0};
			
			break;
		}
	}
	
	//通过to对应的id号找到对应用套接字->套接字才能发数据
	for(int i=0; i<MAXSIZE; i++)
	{
		
		if(cinfo[i].sockfd != 0  && strcmp(cinfo[i].id, toid)==0)
		{
			
			char tmpbuffer[1024]={0};
			sprintf(tmpbuffer, "{\"type\":\"2\",\"from\":\"%s\",\"data\":\"%s\"}", fromid, data);
			//发送数据
			write(cinfo[i].sockfd, tmpbuffer, strlen(tmpbuffer)+1);
			//发送反馈信息{type:1}
			break;
		}
	}
	printf("[clientfd=%d]%s\n",clientfd,  recvbuffer);
	//解析接收到的数据, 从链表或数组中找到对应用套接字描述符再发送数据
}

}


客户端代码:



#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
void *recv_thread(void* arg);

int main(void)
{
//1.创建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror(“socket fail”);
return -1;
}

//2.连接服务器
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET ;
addr.sin_port = htons(8989);
addr.sin_addr.s_addr = inet\_addr("192.168.24.19");
int ret = connect(sockfd, (struct sockaddr\*)&addr, sizeof(addr));


//创建线程接收服务器的数据
pthread_t tid = 0;
pthread\_create(&tid, NULL, recv_thread, (void\*)&sockfd);

char id[16]={0};//存储用户id
printf("请输入登录的ID:"); scanf("%s", id);
//打包发送的数据
char sendbuffer[128]={0}; //存储打包好格式的数据{id:"99999", to:"", data:""}
sprintf(sendbuffer, "{\"id\":\"%s\", \"to\":\"\", \"data\":\"\"}",id);

//发送数据(登录)
write(sockfd, sendbuffer, strlen(sendbuffer)+1);


//定义存储发送的数据
char senddata[1024];
//存储接收数据的id号
char toid[16];
while(1)
{
	printf("请输入要发送的数据:");scanf("%s", senddata);
	printf("请输入接收ID:");scanf("%s", toid);

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值