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;
}

实现了简单的一对多的通信,但是其中一个客户端终止时,会出现,数据的不一致性,可以通过构造一个数据结构来解决问题

posted @ 2018-04-16 21:18  带头大哥小白  阅读(362)  评论(0编辑  收藏  举报