fengxinlinux
Rotation.
采纳率50%
2016-08-19 13:32

关于socket客户端发送数据正常,而服务器收到的数据为空

5
已采纳

我写了一个简单的聊天程序,服务器和客户端接受发送数据都通过定义的同一个结构体,为什么在本机测试,开两个终端都没有问题,客户端和服务器分开在不同的电脑上测试时,客户端发送数据正常,而此时服务器收到的结构体里的数据为空是怎么回事?服务器用的epoll单线程,客户端用的双线程

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

4条回答

  • fengxinlinux Rotation. 5年前

    服务器代码

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include"message.h"

    #define PORT 6666 //服务器端口
    #define LISTEN_SIZE 1024 //连接请求队列的最大长度
    #define EPOLL_SIZE 1024 //监听的客户端的最大数目
    #define BUF_MAX 257 //读取缓存区最大字节

    time_t timep; //记录当前时间

    typedef struct cli_data //记录在线用户信息的结构体
    {
    int cli_fd; //记录连接的用户套接字
    char username[21]; //记录账号,最大20位
    struct cli_data* next;
    }cli_data;
    typedef struct user //记录用户账号信息的结构体
    {
    char username[21];
    char pwd[21];
    }user;
    typedef struct group
    {
    char username[100][21];
    int groupfd[100];
    char groupname[21];
    int n;
    }group;
    group taolun[100]; //全局讨论组
    char* my_time() //输出当前时间
    {
    time(&timep);
    char* p=ctime(&timep);
    return p;
    }

    cli_data* head; //创建头结点
    cli_data* create() //创建一个带头节点的链表,储存已连接的用户
    {
    cli_data* head;
    head=(cli_data*)malloc(sizeof(struct cli_data));
    head->next=NULL;
    return head;
    }
    cli_data* insert() //插入链表
    {

    cli_data* temp=head;
    cli_data* new;
    new=(cli_data*)malloc(sizeof(cli_data));
    new->next=NULL;
    
    while(temp->next!=NULL)
    {
        temp=temp->next;
    }  
    temp->next=new;
    
    return new;
    

    }
    void delete(cli_data* head,int cli_fd) //链表的删除
    {
    cli_data* temp,*last;
    temp=head->next;
    last=head;
    while(temp!=NULL&&temp->cli_fd!=cli_fd)
    {
    last=temp;
    temp=temp->next;
    }
    if(temp!=NULL&&temp->cli_fd==cli_fd)
    {
    last->next=temp->next;
    free(temp);
    }
    }
    void my_err(char* string)
    {
    perror(string);
    exit(1);
    }
    void my_path(char*dir,char* filename,char* path) //将目录和文件名连接成一个路径
    {
    strcpy(path,dir);
    strcat(path,"/");
    strcat(path,filename);
    }
    void send_message(struct message recv_buf,int conn_fd) //向客户端发送信息
    {
    struct message send_buf;
    send_buf=recv_buf;
    int n=send_buf.n;
    int fd;
    struct user user_data;
    int ret=0; //用来表示注册账号是否存在或账号密码信息是否匹配
    FILE* fp;
    cli_data* temp; //在线用户链表临时指针
    char path[256]; //储存文件路径
    char friendname[21]; //储存用户好友用户名
    int i=0;
    fp=fopen("passwd.txt","a+");
    fclose(fp);

    switch(n)
    {
        case 0:  {  //注册账号
        if((fd=open("passwd.txt",O_RDWR|O_APPEND))<0)
        {
            my_err("open");
        }
        while(read(fd,&user_data,sizeof(struct user))>0)
        {
            if(strcmp(user_data.username,send_buf.username)==0)
            {
                send_buf.n=-2;
                ret=1;
                break;
            }
        }
        if(!ret)
        {
            strcpy(user_data.username,recv_buf.username);
            strcpy(user_data.pwd,recv_buf.pwd1);
            send_buf.n=22;
            if(write(fd,&user_data,sizeof(struct user))<0)
            {
                my_err("write");
            }
            close(fd);
    
            int fd,stdoutfd;
            fd=open("log_file",O_RDWR|O_CREAT|O_APPEND);
            stdoutfd=dup(1);
            printf("a user register,username:%s,time:%s",user_data.username,my_time());
            dup2(fd,1);
            printf("a user register,username:%s,time:%s",user_data.username,my_time());
            dup2(stdoutfd,1);
            close(fd);
            close(stdoutfd);
    
    
            mkdir(user_data.username,07777);  //创建用户所属目录
            my_path(user_data.username,user_data.username,path);
            fd=open(path,O_RDWR|O_CREAT|O_APPEND,0777);
            if(fd<0)
            {
                printf("创建用户好友文件失败\n");
            }
            close(fd);
    
    
    
    
        }
        if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
        {
            printf("向客户端发送数据失败\n");
        }
        break;
    }
    
        case 1:  {//登陆 
        if((fd=open("passwd.txt",O_RDONLY))<0)
        {
            my_err("open");
        }
        while(read(fd,&user_data,sizeof(struct user))>0)
        {
            if(strcmp(user_data.username,send_buf.username)==0)
            {
                if(strcmp(user_data.pwd,send_buf.pwd1)==0)
                {
                    ret=1;
                    break;
                }
            }
        }
        if(ret)
        send_buf.n=11;
        else
        send_buf.n=-1;
        if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
        {
            printf("向客户端发送数据失败\n");
            return;
        }
        if(send_buf.n==11)
        {
          int fd,stdoutfd;
          fd=open("log_file",O_CREAT|O_RDWR|O_APPEND);
          printf("a user is login,username:%s,time:%s",send_buf.username,my_time());
          stdoutfd=dup(1);
          dup2(fd,1);
          printf("a user is login,username:%s,time:%s",send_buf.username,my_time());
          dup2(stdoutfd,1);
          close(fd);
          close(stdoutfd);
    
          temp=insert();
          temp->cli_fd=conn_fd;
          strcpy(temp->username,send_buf.username);
    
          my_path("lixian",send_buf.username,path);  //发送离线消息
          fd=open(path,O_RDONLY);
          if(fd>0)
          {
              send_buf.n=6;
              while(read(fd,send_buf.time,sizeof(send_buf.time))!=0)
              {
                  read(fd,send_buf.from,sizeof(send_buf.from));
                  read(fd,send_buf.chat,sizeof(send_buf.chat));
                  if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
                  {
                      printf("向客服端发送离线消息失败\n");
                      return;
                  }
              }
              close(fd);
              fd=open(path,O_RDWR|O_CREAT|O_TRUNC);
              close(fd);
          }
        }
    
        break;
    }
    
    
        case 3:   { //添加好友
        temp=head->next;
    
        my_path(send_buf.from,send_buf.from,path);           //防止重复添加好友
        fd=open(path,O_RDONLY);
        if(fd<0)
        {
            printf("打开用户好友文件失败\n");
            return;
        }
        while(read(fd,friendname,sizeof(friendname))!=0)
        {
            if(strcmp(friendname,send_buf.to)==0)
            {
                send_buf.n=-3;
                if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
                {
                    printf("向客户端发送数据失败\n");
                    return;
                }
                close(fd);
                return;
            }
        }
        while(temp!=NULL)
        {
    
            if(strcmp(temp->username,send_buf.to)==0)  //找到指定在线好友
            { 
               ret=1;
                break;
            }
            temp=temp->next;
        }
        if(ret)
        {
    
    
            int to_fd=temp->cli_fd;        //向另一用户征求是否同意添加好友
    
    
            send(to_fd,&send_buf,sizeof(struct message),0);
            recv(to_fd,&send_buf,sizeof(struct message),0);
    
    
            if(send_buf.n==33)
            {
                my_path(send_buf.from,send_buf.from,path);//写入用户好友文件
                fd=open(path,O_RDWR|O_APPEND);
                if(write(fd,&send_buf.to,sizeof(send_buf.to))<0)
                {
                  printf("写入用户好友失败\n");
                  send_buf.n=-3;
                }
                close(fd);
               my_path(send_buf.from,send_buf.to,path);   //创建用户与该好友的聊天记录文件
               fd=open(path,O_RDWR|O_CREAT|O_TRUNC,0777);
               close(fd);
    
    
                my_path(send_buf.to,send_buf.to,path);    //写入另一用户好友文件
                fd=open(path,O_RDWR|O_APPEND);
                write(fd,&send_buf.from,sizeof(send_buf.from));
                close(fd);
                my_path(send_buf.to,send_buf.from,path);  //创建另一用户与该好友的聊天记录文件
                fd=open(path,O_RDWR|O_CREAT|O_TRUNC,0777);
                close(fd);
    
            }
        }
    
        else
        send_buf.n=-3;
        if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
        {
            printf("send error\n");
        }
        break;
    }
    
        case 4:   {//查看好友列表 
        my_path(recv_buf.username,recv_buf.username,path);  //连接用户好友文件路径
        fd=open(path,O_RDONLY);
        while(read(fd,send_buf.friendname[i++],sizeof(recv_buf.username))!=0);
        send_buf.friendname[i][0]='\0';
    
        if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
        {
            printf("send error\n");
    
        }
        break;}
    
        case 44:    { //查看在线好友
        my_path(recv_buf.username,recv_buf.username,path);  //连接用户好友文件路径
        fd=open(path,O_RDONLY);
    
    
        while(read(fd,friendname,sizeof(friendname))!=0)
        {
            int n=0;
            temp=head->next;
            while(temp!=NULL)
            {
                if(strcmp(temp->username,friendname)==0)
                {
                    n=1;
                    break;
                }
                else
                temp=temp->next;
            }
            if(n)
            {
                strcpy(send_buf.friendname[i++],friendname);
            }
    
        }
        send_buf.friendname[i][0]='\0';
        if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
        {
           printf("send error\n");                                                    
        }
        break;
       }
    
        case 5:    //删除好友
       {
           int i=0;
           int ret=0;
           my_path(send_buf.from,send_buf.from,path);
           fd=open(path,O_RDONLY);
           if(fd<0)
           {
               printf("打开用户好友文件失败\n");
               send_buf.n=-5;
           }
           while(read(fd,send_buf.friendname[i++],sizeof(send_buf.username))!=0)
           send_buf.friendname[i][0]='\0';
           i=0;
           close(fd);
           while(strlen(send_buf.friendname[i])!=0)
           {
               if(strcmp(send_buf.friendname[i],send_buf.to)==0)
               {
                   strcpy(send_buf.friendname[i],"\n");
                   ret++;
               }
               i++;
           }
           fd=open(path,O_RDWR|O_CREAT|O_TRUNC);
           if(fd<0)
           {
               printf("打开用户好友文件失败\n");
               send_buf.n=-5;
    
           }
           i=0;
           while(strlen(send_buf.friendname[i])!=0)
           {
               if(strcmp(send_buf.friendname[i],"\n")!=0)
               {
                   if(write(fd,send_buf.friendname[i],sizeof(send_buf.username))<0)
                   {
                       printf("写入用户好友文件失败\n");
                       send_buf.n=-5;
                   }
               }
               i++;
    
           }
           close(fd);
    
    
           i=0;
           my_path(send_buf.to,send_buf.to,path);
           fd=open(path,O_RDONLY);      //读取删除对象的好友列表
           if(fd<0)
           {
               printf("打开删除对象好友文件失败\n");
               send_buf.n=-5;
           }
           while(read(fd,send_buf.friendname[i++],sizeof(send_buf.username))!=0);
           send_buf.friendname[i][0]='\0';
           close(fd);
           i=0;
    
           while(strlen(send_buf.friendname[i])!=0)
           {
               if(strcmp(send_buf.friendname[i],send_buf.from)==0)
               strcpy(send_buf.friendname[i],"\n");
               i++;
           }
           i=0;
           fd=open(path,O_RDWR|O_CREAT|O_TRUNC);
           if(fd<0)
           {
               printf("打开删除对象好友文件失败\n");
               send_buf.n=-5;
           }
           while(strlen(send_buf.friendname[i])!=0)
           {
               if(strcmp(send_buf.friendname[i],"\n")!=0)
               {
                   if(write(fd,send_buf.friendname[i],sizeof(send_buf.username))<0)
                   {
                       printf("写入删除对象好友文件失败\n");
                       send_buf.n=-5;
                   }
               }
               i++;
           }
           close(fd);
           ret++;
           if(ret==2)
           send_buf.n=55;
           else
           send_buf.n=-5;
    
           if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
           {
               printf("向客户端发送信息失败\n");
               return;
           }
           break;
       }
    
       case 6:   //私聊
       {
    
           int i=0,ret=0;
           my_path(send_buf.from,send_buf.from,path);
           fd=open(path,O_RDONLY);
           while(read(fd,send_buf.friendname[i++],sizeof(send_buf.username))!=0);
           send_buf.friendname[i][0]='\0';
           close(fd);
           i=0;
           while(strlen(send_buf.friendname[i])!=0)
           {
               if(strcmp(send_buf.friendname[i],send_buf.to)==0)
               {
                   ret=1;
                   break;
    
               }
               i++;
           }
           if(ret)
           {
               temp=head->next;
               while(temp!=NULL)
               {
                   if(strcmp(temp->username,send_buf.to)==0)
                   {
                       my_path(send_buf.from,send_buf.to,path);
                       fd=open(path,O_RDWR|O_CREAT|O_APPEND);
                       if(fd<0)
                       {
                           printf("打开记录用户聊天记录文件失败\n");
                       }
    
                       if(send(temp->cli_fd,&send_buf,sizeof(struct message),0)<0)
                       {
                           printf("发送用户消息失败\n");
                           return;
                       }
                       else
                       {
                           int stdoutfd=dup(1);
                           dup2(fd,1);
                           printf("%s",send_buf.time);
                           printf("我@%s:%s\n",send_buf.to,send_buf.chat);
                           dup2(stdoutfd,1);
                           close(fd);
    
                           my_path(send_buf.to,send_buf.from,path);
                           open(path,O_RDWR|O_CREAT|O_APPEND);
                           if(fd<0)
                           {
                               printf("打开记录用户聊天记录文件失败\n");
                               return;
                           }
                           dup2(fd,1);
                           printf("%s",send_buf.time);
                           printf("%s@我:%s\n",send_buf.from,send_buf.chat);
                           dup2(stdoutfd,1);
                           close(fd);
                           close(stdoutfd);
    
                           return;
                       }
    
                   }
                   temp=temp->next;
               }
               my_path("lixian",send_buf.to,path);
    
               fd=open(path,O_RDWR|O_CREAT|O_APPEND,0777);
               if(fd<0)
               {
                   printf("打开指定用户离线消息文件\n");
                   return;
               }
               write(fd,send_buf.time,sizeof(send_buf.time));
               write(fd,send_buf.from,sizeof(send_buf.from));
               write(fd,send_buf.chat,sizeof(send_buf.chat));
               close(fd);
    
           }
           else
           {
               send_buf.n=-6;
               if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
               {
                   printf("向客户端发送信息失败\n");
                   return;
               }
           }
           break;
    
       }
    
       case 77:   //创建讨论组
       {
           int i=1;
           while(taolun[i].n!=0)
           i++;
           if(i<100)
           {
               taolun[i].n=1;
               send_buf.groupi=i;
               strcpy(taolun[i].username[0],send_buf.from);
               strcpy(taolun[i].groupname,send_buf.groupname);
               taolun[i].groupfd[0]=conn_fd;
           }
           else
           send_buf.n=-77;
    
           if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
           {
               printf("向客户发送信息失败\n");
               return;
           }
           break;
    
       }
    
       case 777:   //邀请在线好友加入讨论组
       {
           int ret=0;
           int i=0;
           my_path(send_buf.from,send_buf.from,path);
           fd=open(path,O_RDONLY);
           if(fd<0)
           {
               printf("打开用户好友文件失败\n");
               send_buf.n=-777;
           }
           while(read(fd,send_buf.friendname[i],sizeof(send_buf.username))!=0)
           {
               if(strcmp(send_buf.to,send_buf.friendname[i])==0)
               {
                   ret=1;
                   break;
               }
           }
           if(ret)
           {
               temp=head->next;
               while(temp!=NULL)
               {
                   if(strcmp(send_buf.to,temp->username)==0)
                   {
                       int j=0,k=send_buf.groupi;
                       send(temp->cli_fd,&send_buf,sizeof(struct message),0);
                       while(taolun[k].groupfd[j]!=0)
                       {
                           j++;
                       }
                       taolun[k].groupfd[j]=temp->cli_fd;
                       strcpy(taolun[k].username[j],send_buf.to);
                       return;
                   }
                   temp=temp->next;
               }
           }
           send_buf.n=-777;
           send(conn_fd,&send_buf,sizeof(struct message),0);
           break;
       }
    
       case 7:  //群聊
       {
    
           int i=send_buf.groupi,j=0;
           while(taolun[i].groupfd[j]!=0)
           {
               if(taolun[i].groupfd[j]!=conn_fd&&taolun[i].groupfd[j]!=-1)
               {
                   send(taolun[i].groupfd[j],&send_buf,sizeof(struct message),0);
               }
               j++;
           }
           break;
       }
    
       case -7: //退出讨论组
       {
           int i=send_buf.groupi,j=0;
           while(taolun[i].groupfd[j]!=conn_fd)
           {
               j++;
           }
           if(j==0)
           {
               j=1;
               send_buf.n=-7777;
               while(taolun[i].groupfd[j]!=0&&taolun[i].groupfd[j]!=-1)
               {
                   send(taolun[i].groupfd[j],&send_buf,sizeof(struct message),0);
                   j++;
               }
               taolun[i].n=0;
               memset(&taolun[i],0,sizeof(taolun[i]));
           }
           else
           taolun[i].groupfd[j]=-1;
           break;
       }
    
       case 7777:  //查看讨论组成员
       {
           int i=send_buf.groupi,j=0,k=0;;
           while(taolun[i].groupfd[j]!=0&&taolun[i].groupfd[j]!=-1)
           {
               strcpy(send_buf.friendname[k++],taolun[i].username[j]);
               j++;
           }
           send_buf.friendname[k][0]='\0';
           send(conn_fd,&send_buf,sizeof(struct message),0);
           break;
    
       }
    
       case 8:   //查看与好友聊天记录
       {
           int j=0,ret=0;
           send_buf.n=-8;
           temp=head->next;
           my_path(send_buf.from,send_buf.from,path);
           fd=open(path,O_RDONLY);
           while(read(fd,send_buf.friendname[j++],sizeof(send_buf.username))!=0);
           send_buf.friendname[j][0]='\0';
           j=0;
           while(strlen(send_buf.friendname[j])!=0)
           {
               if(strcmp(send_buf.to,send_buf.friendname[j])==0)
               {
                  ret=1;
                  break;
               }
               j++;
    
           }
           if(ret)
           {
               FILE * fp;
               j=0;
               my_path(send_buf.from,send_buf.to,path);
               fp=fopen(path,"r+");
               while(!feof(fp))
               {
                   fgets(send_buf.chathistory[j],10000,fp);
                   j++;
                   if(j==100)
                   break;
               }
               send_buf.n=8;
           }
           if(send(conn_fd,&send_buf,sizeof(struct message),0)<0)
           {
               printf("向客户端发送数据失败\n");
               return;
           }
    
       }
    
    }
    

    }
    int main()
    {
    int sock_fd,conn_fd; //储存套接字
    struct sockaddr_in cli_addr,serv_addr;
    struct message recv_buf; //读取缓存区
    socklen_t cli_len;
    int epollfd;
    struct epoll_event event;
    struct epoll_event* events;
    int fd;

    memset(taolun,0,sizeof(taolun));
    
    fd=open("log_file",O_RDWR|O_CREAT|O_APPEND);
    close(fd);
    
    
    //创建一个套接字
    sock_fd=socket(AF_INET,SOCK_STREAM,0);
    if(sock_fd<0)
    {
        my_err("socket");
    }
    //设置该套接字使之可以重新绑定端口
    int optval=1;
    if(setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(void*)&optval,sizeof(int))<0)
    {
        my_err("setsockopt");
    }
    //初始化服务器端地址结构
    memset(&serv_addr,0,sizeof(struct sockaddr_in));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(PORT);
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    if(bind(sock_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in))<0)
    {
        my_err("bind");
    }
    //将套接字转化为监听套接字
    if(listen(sock_fd,LISTEN_SIZE)<0)
    {
        my_err("listen");
    }
    cli_len=sizeof(struct sockaddr_in);
    events=(struct epoll_event*)malloc(sizeof(struct epoll_event)*EPOLL_SIZE);
    //创建一个监听描述符epoll,并将监听套接字加入
    epollfd=epoll_create(EPOLL_SIZE);
    if(epollfd==-1)
    {
        my_err("epoll_create");
    }
    event.events = EPOLLIN;
    event.data.fd = sock_fd;
    if(epoll_ctl(epollfd,EPOLL_CTL_ADD,sock_fd,&event)<0)
    {
        my_err("epoll_ctl");
    }
    
    mkdir("lixian",0777);  //创建离线消息目录
    
    head=create();  //创建链表
    while(1)
    {
        int sum=0,i;
        sum=epoll_wait(epollfd,events,EPOLL_SIZE,-1);
        for(i=0;i<sum;i++)
        {
            if(events[i].data.fd==sock_fd)    //有请求连接
            {
                int fd,stdoutfd;
                fd=open("log_file",O_RDWR|O_CREAT|O_APPEND);
                stdoutfd=dup(1);
    
                conn_fd=accept(sock_fd,(struct sockaddr*)&cli_addr,&cli_len);
                if(conn_fd<0)
                {
                    my_err("accept");
                }
    
                event.events = EPOLLIN | EPOLLRDHUP;
                event.data.fd = conn_fd;
                if(epoll_ctl(epollfd,EPOLL_CTL_ADD,conn_fd,&event)<0)   //将新连接的套接字加入监听
                {
                    my_err("epoll_ctl");
                }
                printf("a connet is connected,ip is %s,time:%s",inet_ntoa(cli_addr.sin_addr),my_time());
                dup2(fd,1);
                printf("a connet is connected,ip is %s,time:%s",inet_ntoa(cli_addr.sin_addr),my_time());
                dup2(stdoutfd,1);
                close(fd);
                close(stdoutfd);
    
            }
            else if(events[i].events&EPOLLIN)    //有可读的套接字
            {
    
                memset(&recv_buf,0,sizeof(struct message));  
                recv(events[i].data.fd,&recv_buf,sizeof(struct message),0);
                send_message(recv_buf,events[i].data.fd);
    
            }
            if(events[i].events&EPOLLRDHUP)
            {
                int fd,stdoutfd;
                fd=open("log_file",O_RDWR|O_CREAT|O_APPEND);
                stdoutfd=dup(1);
                delete(head,events[i].data.fd);
                printf("a connet is quit,ip is %s,time:%s",inet_ntoa(cli_addr.sin_addr),my_time());
                dup2(fd,1);
                printf("a connet is quit,ip is %s,time:%s",inet_ntoa(cli_addr.sin_addr),my_time());
                dup2(stdoutfd,1);
                close(fd);
                close(stdoutfd);
                epoll_ctl(epollfd,EPOLL_CTL_DEL,events[i].data.fd,&event);
                close(events[i].data.fd);
            }
        }
    }
    return 0;
    

    }

    
    
    点赞 评论 复制链接分享
  • liuxian13183 刘兆贤 5年前

    电脑是否在同一个局域网内,是否被防火墙屏蔽,端口号有没有被占用

    点赞 评论 复制链接分享
  • baidu_24014585 想翻天 5年前

    http://blog.csdn.net/baidu_24014585/article/details/52244643
    这是我前几天写的,以测试了

    点赞 评论 复制链接分享
  • dabocaiqq dabocaiqq 5年前

为你推荐