网络编程 4.20

UDP网络聊天室通信———服务器

#include "head.h"
#define SER_IP "192.168.125.100"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
    //1.创建结构体
    int sfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sfd==-1){
        perror("socket");
        return -1;
    }
    printf("socket success\n");
    //2.设置端口号快速重启
    int reuse=1;
    if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
        perror("setsockopt");
        return -1;
    }
    printf("setsockopt success\n");
    //3.绑定IP和端口号
    struct sockaddr_in sin;
    sin.sin_family=AF_INET;
    sin.sin_port=htons(SER_PORT);
    sin.sin_addr.s_addr=inet_addr(SER_IP);
    if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){
        perror("bind");
        return -1;
    }
    printf("bind success\n");
    //4.数据交互
    struct sockaddr_in cin;            //客户端发送过来的地址
    socklen_t cinlen=sizeof(cin);
    char cbuf[255];
    //创建用户地址结构体
    int maxi=0;
    struct sockaddr_in rin[100]; //创建用户地址结构体数组
    //创建用户信息结构体
    Msg_t* H=Head_creat();   //创建头结点
    //IO多路复用
    struct pollfd pfds[2];
    pfds[0].fd=0;
    pfds[0].events=POLLIN;
    pfds[1].fd=sfd;
    pfds[1].events=POLLIN;
    char name[20];
    char passwd[20];
    while(1){
        int res=poll(pfds,2,-1);
        if(res==0){
            printf("timr out\n");
            return 0;
        }
        if(res==-1){
            perror("poll");
            return -1;
        }
        //执行到此处说明接发信息被触发
        if(pfds[1].revents==POLLIN){
            bzero(cbuf,sizeof(cbuf));
            recvfrom(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&cin,&cinlen);
            char* p1=cbuf;
            char cfs[211]="";
            strcpy(cfs,p1+41);
            //    printf("cbuf:%s\ncfs:%s\n",p1+41,cfs);
            if(cbuf[0]=='Z'){                                   //表示用户注册
                bzero(name,sizeof(name));
                bzero(passwd,sizeof(passwd));
                char* p1=cbuf;
                strncpy(name,p1+1,20);
                strncpy(passwd,p1+21,20);
                //
                printf("注册用户信息%s||%s\n",name,passwd);     //*********测试用
                //
 
                if(find_node(H,name,passwd)==0){ //如果用户列表不存在则允许创建
                    tail_inst(H,name,passwd);        //用户信息存入链表
                    bzero(cbuf,sizeof(cbuf));
                    cbuf[0]='Y';
                    strcpy(p1+41,"注册成功,欢迎登录聊天系统"); //将成功信息返回客户端
 
                    //    printf("rin[maxi].sin_port=%hd ,rin[maxi].sin_addr.s_addr=%s\n",ntohs(rin[maxi-1].sin_port),inet_ntoa(rin[maxi-1].sin_addr));
                    //    printf("cin.sin_port=%hd ,cin.sin_addr.s_addr=%s\n",ntohs(cin.sin_port),inet_ntoa(cin.sin_addr));
 
                    sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&cin,sizeof(cin));
                }else if(find_node(H,name,passwd)!=0){     //用户已存在并通知客户端
                    bzero(cbuf,sizeof(cbuf));
                    cbuf[0]='N';
                    strcpy(p1+41,"用户已存在,请重新输入");   //将失败信息返回客户端
                    sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&cin,sizeof(cin));
                }
            }
            else if(cbuf[0]=='L'){                                 //表示用户登录
                bzero(name,sizeof(name));
                bzero(passwd,sizeof(passwd));
                char* p1=cbuf;
                strncpy(name,p1+1,20);
                strncpy(passwd,p1+21,20);
                int res=find_node(H,name,passwd);
                if(res==1){
                    if(maxi>1024){  //判断登录用户是否过载
                        cbuf[0]='N';
                        strcpy(p1+41,"登录用户已满,请等待后重试\n");
                        sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&cin,sizeof(cin));
                        break;
                    }
                    rin[maxi]=cin;    //*************************将登录信息存入注册数组中
                    maxi++;
            
                    /*    int i=0;
                        while(1){
                        if(rin[i].sin_addr.s_addr=='\0'){
                        rin[i]=cin;
                        break;
                        }
                        i++;   //最小未使用找出i
                        }
                        if(maxi<i){
                        maxi=i;  //留下最大已使用的下标
                        printf("maxi=%d\n",maxi);  ********测试用(暂时弃用)
                        }*/
                    printf("%s:已登录\n",name);                   //给服务端发送提示
                    cbuf[0]='Y';
                    strcpy(p1+41,"已登录");          //将上线信息发送给所有用户
                    for(int j=0;j<maxi;j++){
                        sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&rin[j],sizeof(rin[j]));
                    }
                }else if(res==2){  //密码错误,用户重新输入
                    cbuf[0]='N';
                    strcpy(p1+41,"密码错误,请重试\n");
                    sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&cin,sizeof(cin));
                }else if(res==0){
                    cbuf[0]='N';
                    strcpy(p1+41,"暂无该用户,请注册\n");
                    sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&cin,sizeof(cin));
                }
            }
            else if(cbuf[0]=='C'){                               //表示用户聊天
                char* p1=cbuf;
                bzero(name,sizeof(name));
                cbuf[0]='Y';
                strncpy(name,p1+1,20);
 
                for(int j=0;j<maxi;j++){
                    sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&rin[j],sizeof(rin[j]));
                    printf("rin[%d].sin_port=%d ,rin[maxi].sin_addr.s_addr=%s\n",j,ntohs(rin[j].sin_port),inet_ntoa(rin[j].sin_addr));
                    //printf("cin.sin_port=%d ,cin.sin_addr.s_addr=%s\n",ntohs(cin.sin_port),inet_ntoa(cin.sin_addr));
                }
                printf("用户%s信息发送成功\n",name);
 
            }
            else if(cbuf[0]=='Q'){                                //表示用户退出
                cbuf[0]='Y';
                char* p1=cbuf;
                strcpy(p1+41,"已下线");  
 
                //定义结构体rin[n],将下线信息发送给其他客户 
                for(int j=0;j<=maxi;j++){
                    sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&rin[j],sizeof(rin[j]));
                }
            }
            printf("ss:%s\n",cbuf);
        }
        if(pfds[0].revents==POLLIN){  //向所有客户端发送通知
            bzero(cbuf,sizeof(cbuf));
            char* p1=cbuf;
            char buf[211]="";
            cbuf[0]='Y';
            strcpy(p1+1,"Server:");
            fgets(buf,sizeof(buf),stdin);
            buf[strlen(buf)-1]='\0';
            strcpy(p1+41,buf);
 
            //    show(H);   //********测试用
 
            for(int j=0;j<maxi;j++){
                sendto(sfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&rin[j],sizeof(rin[j]));
                //    printf("rin[%d].sin_port=%d ,rin[maxi].sin_addr.s_addr=%s\n",j,ntohs(rin[maxi-1].sin_port),inet_ntoa(rin[maxi-1].sin_addr));
                //    printf("客户端说了\n");
            }
        }
    }
    //5.关闭文件
    close(sfd);
    return 0;
}

客户端


#include <myinclude.h>
int main(int argc, const char *argv[])
{
    //1.输入要连接的端口号
    char ip[30]="";
    short pt=0;
    printf("请输入IP地址: ");
    scanf("%s",ip);
    while(getchar()!=10);
    printf("请输入端口号: ");
    scanf("%hd",&pt);
    while(getchar()!=10);
    //2.创建套接字
    int cfd=socket(AF_INET,SOCK_DGRAM,0);
    if(cfd==-1){
        perror("socket");
        return -1;
    }
    printf("socket success\n");
    //3.设置端口号快速重启
    int reuse=1;
    if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
        perror("socketopt");
        return -1;
    }
    printf("set setsockopt success\n");
    printf("登陆成功,请稍后\n");
    sleep(1);
 
    //循环执行功能界面
    //准备变量、结构体
    struct sockaddr_in cin;
    socklen_t cinlen=sizeof(cinlen);
    char cbuf[255];
 
    struct sockaddr_in sin;
    sin.sin_family=AF_INET;
    sin.sin_port=htons(pt);
    sin.sin_addr.s_addr=inet_addr(ip);
 
    //使用poll完成IO多路复用
    //
    //数据交互
    struct pollfd pfd[2];
    pfd[0].fd=0;
    pfd[1].fd=cfd;
    pfd[0].events=POLLIN;
    pfd[1].events=POLLIN;
    char name[20];
    char name1[20];
    char passwd[20];
    char buf[211];
    char cfs[211];
    char* p1=cbuf;
 
 
    printf("欢迎加入网络聊天室\n");
    while(1){
        printf("=======1.登录========\n");
        printf("=======2.注册========\n");
        printf("=======0.退出========\n");
        int num;
        scanf("%d",&num);
        while(getchar()!=10);
 
        switch(num){    
        case 1:         //登录、进入聊天界面
            {
                bzero(name,sizeof(name));
                bzero(passwd,sizeof(passwd));
                bzero(cbuf,sizeof(cbuf));
                bzero(buf,sizeof(buf));
                printf("请输入用户名:");
                scanf("%s",name);
                strcpy(name1,name);
                while(getchar()!=10);
                printf("请输入密码:");
                scanf("%s",passwd);
                while(getchar()!=10);
                cbuf[0]='L';
                strncpy(p1+1,name,20);
                strncpy(p1+21,passwd,20);              //将账户密码输入并等待服务端会话
                sendto(cfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&sin,sizeof(sin));
                bzero(cbuf,sizeof(cbuf));
                recvfrom(cfd,cbuf,sizeof(cbuf),0,NULL,NULL);
                if(cbuf[0]=='N'){
                    printf("错误:%s\n",p1+41);
                    break;
                }
                printf("登陆成功,欢迎\n");
                while(1){
                    int res=poll(pfd,2,-1);
                    if(res==0){
                        printf("time out\n");
                        return -1;
                    }else if(res==-1){
                        perror("poll");
                        return -1;
                    }                      //poll设立完成
 
                    
                    char cfs[211]="";
                    if(pfd[0].revents==POLLIN){            //将消息发送给服务器
//*****
                        bzero(cbuf,sizeof(cbuf));
                        bzero(cfs,sizeof(cfs));
                        cbuf[0]='C';
                        strncpy(p1+1,name1,20);
//*****
                        fgets(cfs,sizeof(cfs),stdin);
                    //    printf("cfs:%s\n",cfs);
                        cfs[strlen(cfs)-1]='\0';
                        strcpy(p1+41,cfs);
                    //    printf("cbuf:%s\n",p1+41);
                    
 
                        
                        if(strcmp(cfs,"quit")==0){
                            bzero(cbuf,sizeof(cbuf));
                            cbuf[0]='Q';
                            strcpy(p1+1,name1);
                            sendto(cfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&sin,sizeof(sin));
                            close(cfd);
                            goto END;
                        }
 
                        sendto(cfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&sin,sizeof(sin));
                    //    printf("发送成功\n");
                    }
                    if(pfd[1].revents==POLLIN){     //将从服务器接收到的信息发送给终端
                        bzero(cbuf,sizeof(cbuf));
                        bzero(name,sizeof(name));
                        bzero(buf,sizeof(buf));
                        recvfrom(cfd,cbuf,sizeof(cbuf),0,NULL,NULL);
                        //char* p1=cbuf;
                        //char name[20]="";
                        strncpy(name,p1+1,20);
                        strncpy(buf,p1+41,211);
                        printf("%s:%s\n",name,buf);
                    //    printf("接收成功\n");                  //***********测试用
                    }
                }
            }
END:            break;
        case 2:     //注册
            {
                bzero(name,sizeof(name));
                bzero(passwd,sizeof(passwd));
                bzero(cbuf,sizeof(cbuf));
                printf("请输入注册名:");
                scanf("%20s",name);
                while(getchar()!=10);
                printf("请输入密码:");
                scanf("%20s",passwd);
                while(getchar()!=10);
                cbuf[0]='Z';
                strncpy(p1+1,name,20);
                strncpy(p1+21,passwd,20);
                sendto(cfd,cbuf,sizeof(cbuf),0,(struct sockaddr*)&sin,sizeof(sin));
                bzero(cbuf,sizeof(cbuf));
                recvfrom(cfd,cbuf,sizeof(cbuf),0,NULL,NULL);
 
                if(cbuf[0]=='N'){
                    printf("错误:%s\n",p1+41);
                    break;
                }else if(cbuf[0]='Y'){
                    printf("%s\n",p1+41);
                }
            }
            break;
        case 0:     //退出客户端
            {
                printf("已退出聊天系统\n");
                return 0;
            }
            break;
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值