Linux一对多的通信
客户端:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/signal.h>
#define MAXLEN 1024
typedef struct mysocketinfo{
int socketcon;
unsigned long ipaddr;
unsigned short port;
}_mysocketinfo;
void *fun_thrreceivehandler(void *socketcon);
const char *ip="127.0.0.1";
const int port=8888;
int main()
{
ssize_t size=0;
//signal(SIGQUIT,SIG_IGN);
printf("start socket\n");
int socketcon=socket(AF_INET,SOCK_STREAM,0);
if(socketcon<0)
{
perror("socket error\n");
exit(1);
}
struct sockaddr_in server_addr;
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=inet_addr(ip);
server_addr.sin_port=htons(port);
printf("socketcon:%d\n",socketcon);
int res_con=connect(socketcon,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr));
if(res_con!=0)
{
perror("connect error\n");
exit(2);
}
printf("连接成功\n");
pthread_t thrreceive;
pthread_create(&thrreceive,NULL,fun_thrreceivehandler,&socketcon);
while(1){
char buf[MAXLEN];
memset(buf,'\0',sizeof(buf));
size=read(STDIN_FILENO,buf,sizeof(buf)-1);
if(size>0)
{
buf[size]='\0';
}
else if(size==0)
{
printf("不能为空\n");
break;
}
else{
perror("read error\n");
break;
}
int sendmsg_len=write(socketcon,buf,size);
if(sendmsg_len>0)
{
printf("发送成功,客户端套接字:%d\n",socketcon);
}
else{
printf("发送失败!\n");
}
sleep(2);
}
close(socketcon);
exit(0);
}
void *fun_thrreceivehandler(void *socketcon)
{
while(1)
{
char buffer[MAXLEN];
int _socketcon=*((int*)socketcon);
int buffer_length=read(_socketcon,buffer,MAXLEN);
buffer[buffer_length+1]='\0';
if(buffer_length<=0)
{
printf("空数据\n");
exit(0);
}
printf("服务器:%s\n",buffer);
}
exit(0);
}
服务端:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#define MAXLEN 1024
#define MAXTHR 10
const int port=8888;
const char *service_ip="127.0.0.1";
//记录线程的变量
int pthreadnum=0;
//连接到的客户端的数量
int conclientcount=0;
typedef struct mysocketinfo{
int socketcon;
char *ipaddr;
uint16_t port;
}_mysocketinfo;
//
struct mysocketinfo arrconsocket[10];
//接受客户端线程列表
//接收到的客户端线程
pthread_t arrthrreceiveclient[10];
//接受到的客户端的数量
int thrreceiveclientcount=0;
//删除杀死的线程
int delete_client(void *fp,int num)
{
int i=0;
pthread_t *ps=(pthread_t *)fp;
if(num<1)
{
return 0;
}
for(i=num;i<thrreceiveclientcount;i++)
{
ps[i]=ps[i+1];
}
return 1;
}
int checkthriskill(pthread_t thr)
{
//1存在,0不存在
int res=1;
//判断线程是否存在
int res_kill=pthread_kill(thr,0);
if(res_kill==0)
{
res=0;
}
return res;
}
void *fun_thrreceivehandler(void *socketcon){
char buffer[MAXLEN];
int buffer_length;
int _socketcon;
while(1){
memset(buffer,'\0',sizeof(buffer));
_socketcon=*((int*)socketcon);
printf("接收套接字:%d\n",_socketcon);
buffer_length=read(_socketcon,buffer,MAXLEN);
if(buffer_length==0){
printf("不能为空\n");
break;
}
else if(buffer_length<0){
printf("接受客户端数据失败了\n");
break;
}
buffer[buffer_length]='\0';
printf("%d:%s\n",_socketcon,buffer);
sleep(1);
}
printf("接受数据线程结束\n");
}
void *fun_thraccepthander(void *socketlisten){
char buf[MAXLEN];
ssize_t size;
while(1){
int sockaddr_in_size=sizeof(struct sockaddr_in);
struct sockaddr_in client_addr;
int socklisten1=*((int *)socketlisten);
int socketcon=accept(socklisten1,(struct sockaddr*)(&client_addr),(socklen_t *)(&sockaddr_in_size));
if(socketcon<0){
perror("accept error\n");
exit(5);
}
else{
printf("accept success\n");
printf("ip:%s,port:%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
}
++conclientcount;
printf("在线人数:%d\n",conclientcount);
printf("连接套接字:%d\n",socketcon);
_mysocketinfo socketinfo;
socketinfo.socketcon=socketcon;
socketinfo.ipaddr=inet_ntoa(client_addr.sin_addr);
socketinfo.port=client_addr.sin_port;
arrconsocket[conclientcount]=socketinfo;//成功,从1开始的
//接受消息
pthread_t thrreceive=0;
pthread_create(&thrreceive,NULL,fun_thrreceivehandler,&socketcon);
arrthrreceiveclient[thrreceiveclientcount]=thrreceive;
thrreceiveclientcount++;
sleep(1);
}
}
int main()
{
ssize_t size=0;
sigset_t newmask,oldmask,pendmask;
sigemptyset(&newmask);
sigaddset(&newmask,SIGQUIT);
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0)
perror("sigprocmask error\n");
sleep(2);
int service_socket=socket(AF_INET,SOCK_STREAM,0);
if(service_socket<0)
{
perror("service create error\n");
exit(1);
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=inet_addr(service_ip);
if(bind(service_socket,(struct sockaddr*)&addr,sizeof(addr))<0)
{
perror("bind error\n");
exit(2);
}
int listen_socket=listen(service_socket,10);
if(listen_socket<0)
{
perror("listen error\n");
exit(3);
}
pthread_t thraccept[MAXTHR];
if(pthread_create(&thraccept[++pthreadnum],NULL,fun_thraccepthander,&service_socket)!=0)
{
perror("pthread_create error\n");
exit(4);
}
sleep(1);
while(1){
int i=0;
int n=0;
int m=0;
for(i=0;i<thrreceiveclientcount;i++){
if(checkthriskill(arrthrreceiveclient[i])==1)
{
printf("有个线程被杀了\n");
if(delete_client((void *)(&arrthrreceiveclient),i)==0)
printf("delete error\n");
thrreceiveclientcount--;
for(n=thrreceiveclientcount+2;n<=conclientcount;n++)
{
arrconsocket[n]=arrconsocket[n+1];
}
conclientcount--;
for(m=thrreceiveclientcount+2;m<=pthreadnum;m++)
{
thraccept[m]=thraccept[m+1];
}
pthreadnum--;
}
}
printf("当前接受数据线程:%d\n",thrreceiveclientcount);
if(conclientcount<=0)
{
printf("客户端没有连接\n");
}
else{
int i=0;
char buf[MAXLEN];
memset(buf,'\0',sizeof(buf));
size=read(STDIN_FILENO,buf,sizeof(buf)-1);
if(size>0)
{
buf[size+1]='\0';
}
else if(size==0)
{
printf("不能为空\n");
size=read(STDIN_FILENO,buf,sizeof(buf)-1);
}
else{
perror("read error\n");
break;
}
for(i=0;i<=conclientcount;i++){
int sendmsg_len=write(arrconsocket[i].socketcon,buf,size);
if(sendmsg_len>0)
{
printf("向%s:%d发送成功\n",arrconsocket[i].ipaddr,arrconsocket[i].port);
}
else
{
printf("向%s:%d发送失败\n",arrconsocket[i].ipaddr,arrconsocket[i].port);
}
}
}
sleep(1);
}
printf("等待子进程退出,即将退出!\n");
char *message;
int j=0;
for(j=0;j<pthreadnum;j++)
{
pthread_join(thraccept[j],(void*)&message);
printf("%s\n",message);
}
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0)
perror("sigprocmask error\n");
printf("SIGQUIT unblocked");
return 0;
}
实现了简单的一对多的通信,但是其中一个客户端终止时,会出现,数据的不一致性,可以通过构造一个数据结构来解决问题
技术不分国界