8,12作业

UDP聊天室

服务端

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
 
//打印错误宏函数
#define ERR_MSG(msg) do{\
    fprintf(stderr,"__%d__",__LINE__);\
    perror(msg);\
}while(0)
 
#define PORT 8888
#define IP "192.168.31.124"
 
typedef uint16_t datatype;
 
//链表结构体
typedef struct Node
{
    union{
        datatype data;
        int len;
    };
 
    struct Node *next;
    struct Node *pro;
}cport;
 
//创建存储链表
cport *list_create()
{
    cport *l=(cport *)malloc(sizeof(cport));
    if(NULL==l)
    {
        printf("创建失败\n");
        return NULL;
    }
    l->len=0;
    l->pro=NULL;
    l->next=NULL;
 
    return l;
}
 
//判空
int list_empty(cport *l)
{
    return l->len==0?1:0;
}
 
//申请节点存放数据
cport *node_buy(datatype data)
{
    cport *p=(cport*)malloc(sizeof(cport));
    if(NULL==p)
    {
        printf("申请失败\n");
        return NULL;
    }
    p->data=data;
    p->next=NULL;
    p->pro=NULL;
 
    return p;
}
 
 
//遍历链表
int list_show(cport *l,datatype data)
{
    if(NULL==l)
    {
        return-1;
    }
    if(list_empty(l))
    {
        cport *p=node_buy(data);
        p->pro=l;
        l->next=p;
        l->len++;
    }
    else
    {
        cport*q=l->next;
        while(q!=NULL)
        {
            if(data==q->data)
                return 1;
            q=q->next;
        }
        cport *r=node_buy(data);
        r->next=l->next;
        r->pro=l;
        r->next->pro=r;
        l->next=r;
        l->len++;
        return 2;
    }
    return 0;
}
 
//删除操作
void list_del(cport *l,datatype data)
{
    if(NULL==l)
    {
        return;
    }
    cport *q=l->next;
    while(q!=NULL)
    {
        if(q->data==data)
        {
            if(q->next==NULL)
            {
                q->pro->next=NULL;
                free(q);
                q=NULL;
                l->len--;
            }
            else
            {
                q->pro->next=q->next;
                q->next->pro=q->pro;
                free(q);
                q=NULL;
                l->len--;
            }
            return;
        }
        q=q->next;    
    }
}
 
int sfd;
cport *l; 
 
 
//发送系统消息的线程
void *se_nd(void *arg)
{
    struct sockaddr_in snd_sys;
    snd_sys.sin_family=AF_INET;
    snd_sys.sin_addr.s_addr=inet_addr(IP);
    socklen_t addrlen=sizeof(snd_sys);
 
 
    char buf[128]="";
    while(1)
    {
        char sys[150]="system:";
        bzero(buf,sizeof(buf));
        fgets(buf,sizeof(buf),stdin);
        buf[strlen(buf)-1]=0;
        strcat(sys,buf);
        strcpy(buf,sys);
 
 
        cport *q=l->next;
        while(q!=NULL)
        {
            snd_sys.sin_port=htons(q->data);
            if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr *)&snd_sys,addrlen)<0)
            {
                ERR_MSG("sendto");
                return NULL;
            }
            q=q->next;
        }
    }
}
 
int main(int argc, const char *argv[])
{
    //创建报式套接字
    sfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sfd<0)
    {
        ERR_MSG("socket");
        return -1;
    }
 
    //填充服务器的IP地址以及端口号
    struct sockaddr_in sin;
    sin.sin_family=AF_INET;
    sin.sin_port =htons(PORT);
    sin.sin_addr.s_addr =inet_addr(IP);
 
    //绑定IP地址和端口号
    if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
    {
        ERR_MSG("bind");
        return -1;
    }
    
    //存储接收到的数据包来自哪里
    struct sockaddr_in rcv_msg;
    socklen_t addrlen=sizeof(rcv_msg);
 
    //发送出去的数据包
    struct sockaddr_in snd_msg;
    snd_msg.sin_family=AF_INET;
    snd_msg.sin_addr.s_addr=inet_addr(IP);
    socklen_t addrlen2=sizeof(snd_msg);
 
    
    //接收数据的双向链表
    l=list_create();
    if(NULL ==l)
    {
        printf("创建失败\n");
        return -1;
    }
    
    char buf[128]="";
    char name[10]="";
    pthread_t td;
    pthread_create(&td,NULL,se_nd,NULL);
 
    while(1)
    {
        bzero(buf,sizeof(buf));
        if(recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr *)&rcv_msg,&addrlen)<0)
        {
            ERR_MSG("recvfrom");
            return -1;
        }
        printf("%d:%s\n",ntohs(rcv_msg.sin_port),buf);
        //printf("[%s:%d]:%s\n",inet_ntoa(rcv_addrmsg.sin_addr),ntohs(rcv_addrmsg.sin_port),buf);
        cport *q=l->next;
        switch(list_show(l,ntohs(rcv_msg.sin_port)))
        {
 
            //聊天室内已有这个成员
        case 1:
            //如果发送过来的不是退出,就加上端口号发给除它的所有人
            if(strcmp("quit",buf)!=0)
            {
                sprintf(name,"%d%c",ntohs(rcv_msg.sin_port),':');
                strcat(name,buf);
                strcpy(buf,name);
            }
            //如果发送过来的是退出,就删除它并加上端口号并发信息给除它以外的所有人
            else if(strcmp("quit",buf)==0)
            {
                sprintf(name,"%d",ntohs(rcv_msg.sin_port));
                strcpy(buf,name);
                strcat(buf,"已退出");
 
                //删除操作
                list_del(l,ntohs(rcv_msg.sin_port));
            }
            while(q!=NULL)
            {
                if(q->data==ntohs(rcv_msg.sin_port))
                {
                    q=q->next;
                    continue;
                }
                snd_msg.sin_port=htons(q->data);
                if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr *)&snd_msg,addrlen2)<0)
                {
                    ERR_MSG("sendto");
                    return -1;
                }
                q=q->next;
            }
            break;
        
            //聊天室内的新成员
        case 2:
            strcat(buf,"已登陆");
            while(q!=NULL)
            {
                if(q->data==rcv_msg.sin_port)
                    continue;
                snd_msg.sin_port=htons(q->data);
                if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&snd_msg,addrlen2)<0)
                {
                    ERR_MSG("sendto");
                    return -1;
                }
                q=q->next;
            }
            break;
        }
    }
 
    close(sfd);
    return 0;
}

客户端


#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
 
//打印错误宏函数
#define ERR_MSG(msg) do{\
    fprintf(stderr,"__%d__",__LINE__);\
    perror(msg);\
}while(0)
 
#define PORT 6666
#define IP "192.168.31.124"
 
int sfd;
 
void *re_ad(void *arg)
{
    char buf[128]="";
    while(1)
    {
        bzero(buf,sizeof(buf));
        if(recvfrom(sfd,buf,sizeof(buf),0,NULL,NULL)<0)
        {
            ERR_MSG("recvfrom");
            return NULL;
        }
        printf("%s\n",buf);
    }
}
 
int main(int argc, const char *argv[])
{
    //创建报式套接字
    sfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sfd<0)
    {
        ERR_MSG("socket");
        return -1;
    }
 
    //填充客户端的IP地址以及端口号
    struct sockaddr_in sin;
    sin.sin_family=AF_INET;
    sin.sin_port =htons(PORT);
    sin.sin_addr.s_addr =inet_addr(IP);
 
    //绑定IP地址和端口号
    if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
    {
        ERR_MSG("bind");
        return -1;
    }
    
    //存储接收到的数据包来自哪里
    
    //填充服务器的IP地址以及端口号
    struct sockaddr_in cin;
    cin.sin_family=AF_INET;
    cin.sin_port =htons(8888);
    cin.sin_addr.s_addr =inet_addr(IP);
    
    //连接到服务器
    if(connect(sfd,(struct sockaddr *)&cin,sizeof(cin))<0)
    {
        ERR_MSG("connect");
        return -1;
    }
    
    printf("连接到服务器成功\n您的端口是%d,请输入端口",PORT);
 
    //创建读取进程
    pthread_t td;
    pthread_create(&td,NULL,re_ad,NULL);
 
    char buf[128]="";
    while(1)
    {
        bzero(buf,sizeof(buf));
        fgets(buf,sizeof(buf),stdin);
        buf[strlen(buf)-1]=0;
 
        if(sendto(sfd,buf,sizeof(buf),0,NULL,0)<0)
        {
            ERR_MSG("sendto");
            return -1;
        }
        if(strcmp("quit",buf)==0)
            exit(0);
    }
    close(sfd);
    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值