(完善之后的程序)linuxTCP一对多通信

服务端:

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>

#define MAXLEN 1024
#define MAXTHR 10

const int port=8888;
const char *ip="127.0.0.1";

typedef struct mysocketinfo{
    int socketcon;
    char *ipaddr;
    uint16_t port;
}_mysocketinfo;

pthread_t arrthrreceiveclient[10];
struct mysocketinfo arrconsocket[10];
int arr=0;

int checkthriskill(pthread_t thr)
{
       //1存在,0不存在
        int res=1;
        //判断线程是否存在
        int kill_rc=pthread_kill(thr,0);

        if(kill_rc==3)
            printf("指定的线程不存在或已退出
");
        else if(kill_rc==2)
            printf("信号无效
");
        else
            printf("指定线程是活着的
");

        if(kill_rc==0)
        {
        res=0;
        }
        return res;
}

//接收消息函数
void *fun_thrreceivehandler(void *socketcon){
    char buffer[MAXLEN];
    int buffer_length;
    int socketcon1;


    socketcon1=*((int*)socketcon);
    while(1){
        memset(buffer,'',sizeof(buffer));//或者使用函数bzero(buffer,20);

        printf("接收套接字:%d
",socketcon1);
        buffer_length=read(socketcon1,buffer,MAXLEN-1);
        if(buffer_length<0)
        {
            printf("接收客户端失败了
");
        }
        else if(buffer==NULL)
        {
            pthread_exit("线程退出");   
        }
        if(strcmp(buffer,"quit")==0)
        {
            int i=0;
            int k=0;

            fprintf(stdout,"套接字:%d close",socketcon1);
            for(i=0;i<=arr;i++)
            {
                if(arrconsocket[i]==socketcon1)
                {
                    for(k=i;k<=arr;k++)
                    {
                        arrconsocket[k]=arrconsocket[k+1];
                        arrthrreceiveclient[k]=arrthrreceiveclient[k+1];
                    }
                }
            }

        }
        printf("buffer:%s
",buffer);
        buffer[buffer_length]='';
        printf("客户端%d:%s
",socketcon1,buffer);
        sleep(1);
    }
     printf("接受数据线程结束
");
}

//删除杀死的线程
int delete_client(void *fp,int num)
{
    /*
    int pthreadnum=0;
    int thrreceiveclientcount=0;//接收消息的线程ID
    int conclientcount=0;//在线人数
    */

    int i=0;

    pthread_t *ps=(pthread_t *)fp;

    if(num<1)
    {
        return 0;   
    }

    for(i=num;i<=arr;i++)
    {
        ps[i]=ps[i+1];  
    arrconsocket[i]=arrconsocket[i+1];
    }

    return 1;
}

//处理acceot
void *fun_thraccepthander(void *socketlisten){
    char buf[MAXLEN];
    ssize_t size;
    int sockaddr_in_size=sizeof(struct sockaddr_in);//sockaddr_in结构体的大小
    struct sockaddr_in client_addr;
    int socklisten1=*((int*)socketlisten);
    int socketcon;

    while(1){
    socketcon=accept(socklisten1,(struct sockaddr*)(&client_addr),(socklen_t *)(&sockaddr_in_size));
    if(socketcon<0)
    {
        perror("accept error
");
        exit(5);
    }   
    else{
        printf("accept success
");
            printf("ip:%s,port:%d
",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
    }


    printf("在线人数:%d
",++arr);
        printf("连接套接字:%d
",socketcon);

    arrconsocket[arr].socketcon=socketcon;
    arrconsocket[arr].ipaddr=inet_ntoa(client_addr.sin_addr);
    arrconsocket[arr].port=client_addr.sin_port;

    //接收的消息
    pthread_t thrreceive=0;
    if(pthread_create(&thrreceive,NULL,fun_thrreceivehandler,&socketcon)!=0)
    {
        perror("pthread_create error
");
        exit(6);
    }
    arrthrreceiveclient[arr]=thrreceive;
    sleep(1);
    }

}

void *fun_thrfile(void *socketcon)
{
    int _socketcon=*((int *)socketcon);
    int sockfd,addrlen,n;
    struct sockaddr_in addr;
    char buf[MAXLEN];
    int sock_tmp;
    int count=0;
    int k=0;
    int m=0;

    sockfd=socket(AF_INET,SOCK_DGRAM,0);//服务端的数据报
    if(sockfd<0)
    {
        fprintf(stderr, "socket failed
");  
            exit(EXIT_FAILURE);
    }   

    addrlen=sizeof(struct sockaddr_in);
    bzero(&addr,addrlen);
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=htonl(INADDR_ANY);
    addr.sin_port=htons(9999);

    if(bind(sockfd,(struct sockaddr*)(&addr),sizeof(addr))<0)
    {
        fprintf(stderr, "socket failed
");  
            exit(EXIT_FAILURE);
    }
    puts("bind success");

    bzero(buf,MAXLEN);
    while(1)
    {
        n=recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)(&addr),&addrlen);
        if(n>0)
        {
            sock_tmp=atoi(buf);
            fprintf(stdout,"sock_tmp:%d",sock_tmp);
        }
        else
        {
            count++;
        }
        if(count==3)
        {
            for(k=0;k<=arr;k++)
            {
                if(arrconsocket[k].socketcon==sock_tmp)
                {
                    for(m=k;m<=arr;m++)
                    {
                        arrconsocket[k]=arrconsocket[k+1];
                        arrthrreceiveclient[k]=arrthrreceiveclient[k+1];
                    }
                    arr-=1;
                    break;
                }
            }
        }           
        sleep(3);
    }
}


int main()
{
    int service_socket=socket(AF_INET,SOCK_STREAM,0);//创建服务端的套接字
    if(service_socket<0)//如果创建套接字失败了
    {
        perror("service create error
");
        exit(1);
    }

    struct sockaddr_in addr;//套接字地址结构
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=inet_addr(ip);

    if(bind(service_socket,(struct sockaddr*)&addr,sizeof(addr))<0)//连接套接字结构和套接字
    {
        perror("bind error
");
        exit(2);
    }

    int listen_socket=listen(service_socket,10);//监听套接字
    if(listen_socket<0)//失败的处理
    {
        perror("listen error
");
        exit(3);
    }

    pthread_t thraccept;//创建的线程数组
    //pthread_create创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数
    if(pthread_create(&thraccept,NULL,fun_thraccepthander,&service_socket)!=0)
    {
        perror("pthread_create error
");
        exit(4);
    }
    sleep(1);
    pthread_t thrfile;
    if(pthread_create(&thrfile,NULL,fun_thrfile,&service_socket)!=0)
    {
        perror("pthread_create error
");
        exit(4);
    }
    sleep(1);

    while(1)
    {
        int i=1;
        for(i=1;i<=arr;i++)
        {
            if(checkthriskill(arrthrreceiveclient[i])==1)
            {
                printf("have a thread is killed
");
                if(delete_client((void*)(&arrthrreceiveclient),i)==0)
                {
                    printf("delete_client error
");
                    exit(6);
                }
                --arr;
            }
        }
        printf("当前接收进程数据线程:%d
",arr);
        if(arr<=0)
        {
            printf("没有客户端连接
");
        }
        else
        {
            int i=0;
            char buf[MAXLEN];
            ssize_t size=0;

            memset(buf,'',MAXLEN);
            size=read(STDIN_FILENO,buf,sizeof(buf));
            if(size>0)
            {
                buf[size]='';
            }
            else
            {
                perror("read error
");
                break;
            }

            for(i=1;i<=arr;i++)
            {
                int sendmsg_len=write(arrconsocket[i].socketcon,buf,size);
                if(sendmsg_len>0)
                {
                    printf("向客户端%s:%d发送成功
",arrconsocket[i].ipaddr,arrconsocket[i].port);
                }
                else
                {
                    printf("向客户端%s:%d发送失败
",arrconsocket[i].ipaddr,arrconsocket[i].port);
                }
            }
        }
        //pthread_join(id1,&a1);
        sleep(1);
    }
    if(arr>=1)
    {
        char *message;
        int j=1;
        int res=1;
        printf("等待线程退出
");



            if((res=pthread_join(thraccept,(void*)&message))==0)
            {
                printf("%s
",message);
            }
            else
            {
                printf("pthread_join error:%d
",res);
            }

    }
    else
    {
        printf("没有线程
");
    }
    close(service_socket);
    pthread_kill(thraccept,SIGKILL);
    return(0);
}

客户端:

#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);
void *fun_thrfile(void *socketcon);

const char *ip="127.0.0.1";
const int port=8888;
pthread_t thrreceive;
pthread_t thrfile;
int socketcon;
int sockfd;

int main()
{

    sigset_t newmask,pendmask;

    sigemptyset(&newmask);
    sigaddset(&newmask,SIGQUIT);
    sigaddset(&newmask,SIGINT);
    if(sigprocmask(SIG_BLOCK,&newmask,NULL)<0)
        printf("SIG_BLOCK error
");    

    printf("start socket
");
    socketcon=socket(AF_INET,SOCK_STREAM,0);
    if(socketcon<0)S
    {
        perror("socket error
");
        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
",socketcon);


    int res_con=connect(socketcon,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr));
    if(res_con!=0)
    {
        perror("connect error
");
        exit(2);
    }

    printf("连接成功
");
    if(pthread_create(&thrreceive,NULL,fun_thrreceivehandler,&socketcon)!=0)
    {
    perror("pthread_create error
");
        exit(3);
    }
    sleep(2);
    if(pthread_create(&thrfile,NULL,fun_thrfile,&socketcon)!=0)
    {
        perror("pthread_create error
");
        exit(4);
    }
    sleep(1);

    while(1){
        char buf[MAXLEN];
    int size=0;
        memset(buf,'',sizeof(buf));

        size=read(STDIN_FILENO,buf,sizeof(buf)-1);
        if(size>0)
        {
            buf[size]='';
        }
        else if(size==0)
        {
            printf("不能为空
");
            break;
        }
        else{
            perror("read error
");
            break;
        }

        int sendmsg_len=write(socketcon,buf,size);
        if(sendmsg_len>0)
        {
            printf("发送成功,客户端套接字:%d
",socketcon);
        }
        else{
            printf("发送失败!
");
        }

    if(strcmp(buf,"quit")==0)
    {
        close(socketcon);
            pthread_kill(thrreceive,SIGKILL);
        close(sockfd);
        pthread_kill(thrfile,SIGKILL);
    }

        sleep(2);

    }

    close(socketcon);
    pthread_kill(thrreceive,SIGKILL);
    if(sigpending(&pendmask)<0)
        printf("sigpending error
");
    if(sigismember(&pendmask,SIGQUIT))
        printf("
SIGQUIT Pending
");
    if(sigismember(&pendmask,SIGINT))
        printf("
SIGINT Pending
");
    exit(0);
}

void *fun_thrreceivehandler(void *socketcon)
{
    char buffer[MAXLEN];
    int _socketcon=*((int*)socketcon);
    while(1)
    {
    memset(buffer,'',sizeof(buffer));
        int buffer_length=read(_socketcon,buffer,MAXLEN-1);
        buffer[buffer_length]='';
        if(buffer_length<=0)
        {
            printf("空数据
");
            exit(0);
        }
        printf("服务器:%s
",buffer);
    }
    pthread_kill(thrreceive,SIGKILL);
    exit(0);
}

void *fun_thrfile(void *socketcon)
{
    int _socketcon=*((int *)socketcon);
    int addrlen,n;
    struct sockaddr_in addr;
    int buflength=0;
    char buf[MAXLEN];

    sockfd=socket(AF_INET,SOCK_DGRAM,0);//数据报
    if(sockfd<0)
    {
        fprintf(stderr,"socker failed
");
        exit(EXIT_FAILURE);
    }

    addrlen=sizeof(struct sockaddr_in);
    bzero(&addr,addrlen);//清空addr   
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=htonl(INADDR_ANY);
    addr.sin_port=htons(9999);


    bzero(buf,MAXLEN);
    buflength=sprintf(buf,"%d",_socketcon);
    buf[buflength]='';
    fprintf(stdout,"_socketcon:%d",buf);

    while(1)
    {
        n=sendto(sockfd,buf,buflength,0,(struct sockaddr*)(&addr),addrlen);
        if(n<=0)
        {
            fprintf(stderr,"sendto error
");
            exit(EXIT_FAILURE);
        }
        sleep(1);
    }
    close(sockfd);
    pthread_kill(thrfile,SIGKILL);
    exit(0);
}

完善了以前编写程序出现的一些BUG。

技术不分国界
原文地址:https://www.cnblogs.com/angels-yaoyao/p/12443605.html