简单的UDP聊天室

1.服务器

#include <head.h>
typedef struct Node{
    union{
        int len;
        struct sockaddr_in sin;
    };
    struct Node* next;
}*node;

typedef struct tell{
    char type;          //L:登录  C:聊天   Q:退出
    char name[20];
    char text[128];
}talk;

typedef struct inform{
    char name[20];
    char text[128];
}usr_inf;

typedef struct information{

    struct sockaddr_in cin;
    struct inform usr_inf;

}inf;

#define ERR_MSG(msg) do{\
    fprintf(stderr,"line: %d\n",__LINE__);\
    perror(msg);\
    return -1;\
}while(0);

//#define IP "192.168.74.189"
//#define IP "192.168.8.220"
#define IP "192.168.0.226"
#define PORT 8888

void* getout(void* arg);
void* join(void* arg);
void* traver(void* arg);
void* error(void* arg);
void* forword(void* arg);


node link1;
int sfd;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int main(int argc,const char * argv[])
{   
    sfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sfd < 0){
        ERR_MSG("socket");
        return -1;
    }
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORT);
    sin.sin_addr.s_addr = inet_addr(IP);

    if((bind(sfd,(struct sockaddr*)&sin,sizeof(sin))) < 0){
        ERR_MSG("bind");
        return -1;
    }
    printf("绑定成功\n");
    pthread_t tid,tid1;
    struct sockaddr_in cin;
    socklen_t len = sizeof(cin);
    char buf[128] = "";
    talk infor;
    int res = 0;
    link1 = (struct Node*)malloc(sizeof(struct Node));
    link1->next = NULL;
    link1->len = 0;
    inf node;
    memset(&infor,0,sizeof(infor));
    if((pthread_create(&tid1,NULL,(void*)forword,NULL)) < 0){
        printf("error  __%d__\n",__LINE__);
        return -1;
    }

    while(1){
        res = recvfrom(sfd,&infor,sizeof(infor),0,(struct sockaddr*)&cin,&len);
        if(res < 0){
            ERR_MSG("recvfrom");
            return -1;
        }
        if('L' == infor.type||'l' == infor.type){
            inf urse;
            memset(&urse.cin,0,sizeof(struct Node));
            strcpy(urse.usr_inf.name,infor.name);
            strcpy(urse.usr_inf.text,"上线了!!!");
            urse.cin = cin; 
            if((pthread_create(&tid,NULL,(void*)join,(void*)&urse)) < 0){
                printf("error  __%d__\n",__LINE__);
                return -1;
            }
            pthread_detach(tid);
        }else if('C' == infor.type||'c' == infor.type){
            inf urse;
            strcpy(urse.usr_inf.name,infor.name);
            strcpy(urse.usr_inf.text,infor.text);
            urse.cin = cin; 
        if((pthread_create(&tid,NULL,(void*)traver,(void*)&urse)) < 0){
            printf("error __%d__\n",__LINE__);
            return -1;
        }  
        pthread_detach(tid);

        }else if('Q' == infor.type||'q' == infor.type){
            inf urse;
            strcpy(urse.usr_inf.name,infor.name);
            strcpy(urse.usr_inf.text,"下线了!!!");
            urse.cin = cin; 
            if((pthread_create(&tid,NULL,(void*)getout,(void*)&urse)) < 0){
                printf("error __%d__\n",__LINE__);
                return -1;
            }
            pthread_detach(tid);

        }else{
            inf urse;
            strcpy(urse.usr_inf.name,"**Server**");
            strcpy(urse.usr_inf.text,"WRONG TYPE");
            urse.cin = cin; 
            if((pthread_create(&tid,NULL,(void*)error,(void*)&urse)) < 0){
                printf("error __%d__\n",__LINE__);
                return -1;
            }
        }  
    }
    pthread_mutex_destroy(&mutex);
    return 0;
}
void *traver(void* arg){
    pthread_mutex_lock(&mutex);
    struct information urse_1;
    urse_1 = *(struct information*)arg;
    node p = link1;
    if(0 == link1->len)
    {
        strcpy(urse_1.usr_inf.name,"**Server**");
        strcpy(urse_1.usr_inf.text,"请先登录");
        if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
            printf("error __%d__",__LINE__);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
    }
    for(int i = 0; i < link1->len; i++){
        p = p->next;
        if(0 == memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
            break;
        }
        if(NULL == p->next){
            strcpy(urse_1.usr_inf.name,"**Server**");
            strcpy(urse_1.usr_inf.text,"请先登录");
            if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
                printf("error __%d__",__LINE__);
                pthread_mutex_unlock(&mutex);
                pthread_exit(NULL);
            }
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
    }
    p = link1;
    for(int i = 0; i < link1->len; i++){
        p = p->next;
        if(0 != memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
            if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&p->sin,sizeof(p->sin))) < 0){
                printf("error __%d__",__LINE__);
                break;
            }
        }
          
    }
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
void* join(void* arg){
    pthread_mutex_lock(&mutex);
    struct information urse_1;
    urse_1 = *(struct information*)arg;
    node ptr;
    ptr = (node)malloc(sizeof(struct Node));
    memset(ptr,0,sizeof(struct Node));
    ptr->sin = urse_1.cin;
    node p;
    p = link1;
    printf(" __%d__\n",__LINE__);
    for(int i = 0; i < link1->len; i++){
        p = p->next;
        if(!memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
            strcpy(urse_1.usr_inf.text,"请不要重复登录");
            if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
                printf("error __%d__",__LINE__);
                pthread_mutex_unlock(&mutex);
                pthread_exit(NULL);
            }
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
    }
    p = link1;
    for(int i = 0; i < link1->len; i++){
        p = p->next;
        if(0 != memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){
            if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&p->sin,sizeof(p->sin))) < 0){
                printf("error __%d__",__LINE__);
                break;
            }
        }
          
    }
    strcpy(urse_1.usr_inf.text,"登陆成功");
    strcpy(urse_1.usr_inf.name,"**Server**");
    if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
        printf("error __%d__",__LINE__);
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
    }
    ptr->next = p->next;
    p->next = ptr;
    link1->len++;
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
void* getout(void* arg){//登出
    pthread_mutex_lock(&mutex);
    struct information urse_1;
    urse_1 = *(struct information*)arg;
    node p = link1;
    node q ;
    for(int i = 0; i < link1->len; i++){
        p = p->next;
        if(0 == memcmp(&p->sin,&urse_1.cin,sizeof(p->sin))){//如果他在链表中我就执行给其他人发信息不在链表中我需要他先登录
            break;
        }
        if(NULL == p->next){
            strcpy(urse_1.usr_inf.name,"**Server**");
            strcpy(urse_1.usr_inf.text,"请先登录");
            if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
                printf("error __%d__",__LINE__);
                pthread_mutex_unlock(&mutex);
                pthread_exit(NULL);
            }
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
    }
    p = link1;
    for(int i = 0; i < link1->len; i++){ 
        if(0 == memcmp(&p->next->sin,&urse_1.cin,sizeof(p->sin))){
            q = p ->next;
            p->next = q->next;
            free(q);
            q = NULL;
            link1->len--;
            break;
        }
        p = p->next;
    }
    p = link1;
    for(int i = 0; i < link1->len; i++){
        p = p->next;
        if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&p->sin,sizeof(p->sin))) < 0){
            printf("error __%d__",__LINE__);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }      
    }
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);

}
void* error(void* arg){
    struct information urse_1;
    urse_1 = *(struct information*)arg;

    if((sendto(sfd,&urse_1.usr_inf,sizeof(urse_1.usr_inf),0,(struct sockaddr*)&urse_1.cin,sizeof(urse_1.cin))) < 0){
        printf("error __%d__",__LINE__);
        
    }  
    pthread_exit(NULL);
    return NULL; 
}
void* forword(void* arg){
    usr_inf usr1;
    strcpy(usr1.name,"**Server**");
    char buf[128] = "";
    int i = 0;
    node p = link1;
    int res = 0;
    while(1){
        printf("请输入全体信息>>>>");
        scanf("%s",buf);
        strcpy(usr1.text,buf);
        for(i = 0;i < link1->len;i++){
            p = p->next;
            res = sendto(sfd,&usr1,sizeof(usr1),0,(struct sockaddr*)&p->sin,sizeof(p->sin));
            if(res < 0){
               printf("error __%d__",__LINE__); 
               pthread_exit(NULL);
            }
        }
    }
    pthread_exit(NULL);
}

2.客户端

#include <head.h>
//传递给线程的结构体
struct cli_msg
{
    int newfd;
    struct sockaddr_in cin;
}; 
typedef struct node{
    char type;          //L:登录  C:聊天   Q:退出
    char name[20];
    char text[128];
}talk;
typedef struct inform{
    char name[20];
    char text[128];
}usr_inf;
#define ERR_MSG(msg) do{\
    fprintf(stderr,"line: %d\n",__LINE__);\
    perror(msg);\
    return -1;\
}while(0);

//ip地址和端口
//#define IP "192.168.74.189"
//#define IP "192.168.8.220"
#define IP "192.168.0.226"
#define PORT 8888

void* SEND_to(void* arg);
void* RECV_from(void* arg);

//读和写的结构体定义
talk talk_to;
talk talk_from;

//全局的定义
int sfd = -1;

struct sockaddr_in cin;
socklen_t len = sizeof(cin);

struct sockaddr_in serin;
socklen_t len1 = sizeof(serin);

int main(int argc,const char * argv[])
{
    //客户端
      //udp连接创建报式字节套
    sfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sfd < 0){
        ERR_MSG("socket");
        return -1;
    }
    //printf("%d\n",sfd);
    
    //绑定
    // struct sockaddr_in serin;
    serin.sin_family = AF_INET;
    serin.sin_port = htons(PORT);
    serin.sin_addr.s_addr = inet_addr(IP);
    // socklen_t len1 = sizeof(serin);

    // struct sockaddr_in cin;
    // socklen_t len = sizeof(cin);
    //创建成功后之间分两步进程让两个进程分别读和写

    pthread_t tid,tid1;
    if((pthread_create(&tid,NULL,(void*)SEND_to,NULL)) < 0){
        printf("error %d\n",__LINE__);
        return -1;
    }

    if((pthread_create(&tid1,NULL,(void*)RECV_from,NULL)) < 0){
        printf("error %d\n",__LINE__);
        return -1;
    }

    pthread_join(tid,NULL);
    pthread_detach(tid1);
    pthread_join(tid1,NULL);
    
    return 0;
    
}
//写
void* SEND_to(void* arg){
     int res = 0;
    char idname[20];
    char a;
    char buf[128] = "";
    printf("请输入id>>>>");
    scanf("%s",idname);
    strcpy(talk_to.name,idname);
    while(1){//划分线程
        printf("请输入type(L,Q,C)>>>>\n");
        scanf(" %c",&a);
        talk_to.type = a;
        memset(buf,0,sizeof(buf));
        memset(talk_to.text,0,sizeof(talk_to.text));
        strcpy(talk_to.text,buf);
        if(!('q' == a||'Q' == a||'L' == a||'l' == a)){//只有聊天才使用输入话
            printf("请输入test>>>>\n");
            scanf("%s",buf);
            strcpy(talk_to.text,buf);
        }
        
        //printf("type = %c name = %s text = %s\n",talk_to.type,talk_to.name,talk_to.text);
        //printf("__%d__\n",__LINE__);


        res = sendto(sfd,&talk_to,sizeof(talk_to),0,(struct sockaddr*)&serin,len1);
        if(res < 0){
            printf("error __%d__",__LINE__);
            break;
        }
        if('Q' == a||'q' == a){
            break;
        }

    }
    pthread_exit(NULL);
}
//读
void* RECV_from(void* arg){
    int res = 0;
    usr_inf inf;
    while(1){//读来自服务器的信息  
        res = recvfrom(sfd,&inf,sizeof(inf),0,NULL,NULL);
        if(res < 0){
            printf("error __%d__",__LINE__);
            break;
        }
        //打印信息且只打印name和text
        printf("%s:%s\n",inf.name,inf.text);
    }  
    pthread_exit(NULL); 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值