UDP网络聊天室day7

#include "head.h"
//服务器端
void server_char(int sockfd,list_t *p,MSG_t msg,struct sockaddr_in caddr);
void server_login(int sockfd,list_t *p,MSG_t msg,struct sockaddr_in caddr);
void server_quit(int sockfd,list_t *p,MSG_t msg,struct sockaddr_in caddr);
list_t *Createlist();
int main(int argc, const char *argv[])
{
    if(argc!=3){
        printf("请输入IP地址 端口号\n");
        return -1;
    }
    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        perror("socket error");
        return -1;
    }
    struct sockaddr_in saddr,caddr;
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(atoi(argv[2]));
    saddr.sin_addr.s_addr=inet_addr(argv[1]);
    int len=sizeof(caddr);
    if(bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr))==-1){
        perror("bind error");
        return -1;
    }
    MSG_t msg;
    list_t *p=Createlist();
    while(1){//接收客户端发来的结构体,判断类型,执行相应函数
        recvfrom(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&caddr,&len);
        switch(msg.type)
        {
            case login:
                server_login(sockfd,p,msg,caddr);
                break;
            case chat:
                server_char(sockfd,p,msg,caddr);
                break;
            case quit:
                server_quit(sockfd,p,msg,caddr);
                break;
        }
    }
    close(sockfd);
    return 0;
}
 
void server_char(int sockfd,list_t *p,MSG_t msg,struct sockaddr_in caddr)
{
    while(p->next!=NULL)
    {
        p=p->next;
        //当前用户结点跳过不发送信息
        if(memcmp(&(p->addr),&caddr,sizeof(caddr))==0){
            continue;
        }
        //其他用户发送信息
        sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(p->addr),sizeof(p->addr));
    }
}
void server_login(int sockfd,list_t *p,MSG_t msg,struct sockaddr_in caddr)
{
    sprintf(msg.text,"%s加入chat\n",msg.name);
    printf("%s\n",msg.text);
    while(p->next!=NULL)
    {//向所有链表内用户发送上线信息
        p=p->next;
        sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(p->addr),sizeof(p->addr));
    }
    //向链表添加新用户
    list_t *pnew=(list_t*)malloc(sizeof(list_t));
    pnew->next=NULL;
    p->next=pnew;
    pnew->addr=caddr;
 
}
void server_quit(int sockfd,list_t *p,MSG_t msg,struct sockaddr_in caddr)
{
    list_t *pdel=NULL;
    //将离线信息写入text
    sprintf(msg.text,"%s已下线\n",msg.name);
    while(p->next!=NULL)
    {
        //找到当前用户的位置删除结点
        if(memcmp(&(p->next->addr),&caddr,sizeof(caddr))==0){
            pdel=p->next;
            p->next=pdel->next;
            free(pdel);
            pdel=NULL;
        }else{//非当前用户发送离线信息
            p=p->next;
            sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&(p->addr),sizeof(p->addr));
            }
    }
 
 
}
 
list_t *Createlist()
{
    list_t *p=(list_t*)malloc(sizeof(list_t));
    if(p==NULL)
    {
        perror("malloc error");
        return NULL;
    }
    p->next=NULL;
    return p;
}


#include "head.h"
//客户端
int main(int argc, const char *argv[])
{
    if(argc!=3){
        printf("请输入IP地址 端口号\n");
        return -1;
    }
    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd==-1){
        perror("socket error");
        return -1;
    }
    struct sockaddr_in caddr;
    caddr.sin_family=AF_INET;
    caddr.sin_port=htons(atoi(argv[2]));
    caddr.sin_addr.s_addr=inet_addr(argv[1]);
 
    MSG_t msg;
    printf("请输入用户名:");
    fgets(msg.name,sizeof(msg.name),stdin);
    if(msg.name[strlen(msg.name)-1]=='\n'){
        msg.name[strlen(msg.name)-1]='\0';
    }
    msg.type=login;//发送用户名和登录类型的结构体到服务器
    sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&caddr,sizeof(caddr));
 
    pid_t pid=fork();
    if(pid<0){
        perror("fork error");
        return -1;
    }else if(pid==0){//子进程接收服务器返回的结构体消息
        while(1){
            recvfrom(sockfd,&msg,sizeof(msg),0,NULL,NULL);
            printf("%s:%s\n",msg.name,msg.text);
        }
    }else{//父进程向服务器发送结构体类型消息
        while(1){
            //向结构text写内容
            fgets(msg.text,sizeof(msg.text),stdin);
            
             if(msg.text[strlen(msg.text)-1]=='\n'){
                msg.text[strlen(msg.text)-1]='\0';
                }//在输入内容后添加\0
            
            //输入quit跳出循环下线
             if(strncmp(msg.text,"quit",4)==0){
                msg.type=quit;
                sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&caddr,sizeof(caddr));
                break;
            }else{//非quit正常聊天
                msg.type=chat;
                
                sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&caddr,sizeof(caddr));
                }
        }
        kill(pid,SIGKILL);//循环结束说明用户下线杀死子进程
        wait(NULL);
    }
    close(sockfd);
    return 0;
}

#include <myhead.h>
//重定向list_t用户地址端口链表
typedef struct node
{
    struct sockaddr_in addr;
    struct node *next;
}list_t;
//重定向MSG_t信息结构体
typedef struct msg_t
{
    int type;
    char name[32];
    char text[128];
}MSG_t;
//定义枚举变量
enum type_t
{
    login,
    chat,
    quit,
};

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值