zoukankan      html  css  js  c++  java
  • 解决Linux 下server和client 通过TCP通讯:accept成功接收却报错的问题

      今天在写简单的TCP通讯例子的时候,遇到了一个问题:server 和client能够连接成功,并且client也能够正常发送,但server就是接收不到,在网上搜索一番后,终于解决了问题。在这里整理如下:

      大家要注意的是,一个server端可以连接多个client端,server端的accept()函数负责等待并接收client的连接请求,而且accept()函数将不同client端的sockfd作为返回值。为了保证接收到对应的client端数据,所以在client连接成功且使用recv()函数接收数据的时候,recv()函数的第一个参数应该是accept成功后的返回值。

    实例代码如下:

    1.server端

     1 #include <sys/types.h>
     2 #include <sys/socket.h>
     3 #include <stdio.h>
     4 #include <stdlib.h>
     5 #include <string.h>
     6 #include <errno.h>
     7 #include <unistd.h>
     8 #include <netinet/in.h>
     9 #include <netdb.h>
    10 
    11 #define MAX_MSG_LEN 1024
    12 #define BACKLOG     10 
    13 
    14 int main(int argc,char *arg[])
    15 {
    16     struct sockaddr_in servAddr,clidAddr;
    17     struct hostent *host = NULL;
    18     int Port = 0,socketFd,sin_size;
    19     socklen_t peerlen;
    20     int recLen = 0;
    21     char buf[MAX_MSG_LEN] = {0};
    22     
    23     if(argc<2)
    24     {
    25         printf("please input port number!
    ");
    26         return -1;
    27     }
    28 
    29     //                     ipV4        TCP     0
    30     if((socketFd=socket(AF_INET,SOCK_STREAM,0))==-1)
    31     {
    32         perror("socket");
    33         return -1;
    34     }    
    35     printf("socket fd = %d
    ",socketFd);
    36     
    37     
    38     memset(&servAddr,0,sizeof(struct sockaddr_in));
    39     servAddr.sin_family = AF_INET;
    40     servAddr.sin_port   = htons(atoi(arg[1]));
    41     servAddr.sin_addr.s_addr= INADDR_ANY;
    42     
    43     if(bind(socketFd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr))==-1)
    44     {
    45         perror("bind:");
    46     }
    47     else
    48     {
    49         printf("bind success 
    ");
    50     }
    51     
    52     if(listen(socketFd,BACKLOG)==-1)
    53     {
    54         perror("listen:");
    55     }
    56     else
    57     {
    58         printf("Listening...
    ");
    59     }
    60     sin_size=sizeof(struct sockaddr_in);
    61     
    62     if((socketFd=accept(socketFd,(struct sockaddr *)&clidAddr,&sin_size))==-1)
    63     {
    64             perror("accept:");
    65             return -1;
    66     }
    67         else
    68     {
    69             printf("accept successful!
    ");
    70     }
    71     
    72     while(1)
    73     {
    74         memset(buf,0,sizeof(buf));
    75         if((recLen = recv(socketFd,buf,MAX_MSG_LEN,0))==-1)
    76         {
    77             perror("recv:");
    78         }
    79         else
    80         {
    81             if(recLen>0)
    82             {
    83                 recLen = 0;
    84                 printf("Receive a message:%s
    ",buf);
    85             }
    86         }
    87     }    
    88     close(socketFd);
    89     return 0;
    90 }

    上述代码的关键在于62行:

    if((socketFd=accept(socketFd,(struct sockaddr *)&clidAddr,&sin_size))==-1)
    recv(socketFd,buf,MAX_MSG_LEN,0);
    将sockfd赋值为accept的返回值问题就解决了,为了实验方便,这里一并附上client代码:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <netdb.h>
    
    #define MAX_MSG_LEN 1024
    
    int main(int argc,char *arg[])
    {
        struct sockaddr_in servAddr;
        struct hostent *host = NULL;
        int Port = 0,socketFd;
        char buf[MAX_MSG_LEN] = {0};
        
        if(argc<3)
        {
            printf("please input IP and port number!
    ");
            return -1;
        }
        
        if((host = gethostbyname(arg[1]))==NULL)
        {
            return -1;
        }    
        //                     ipV4        TCP     0
        if((socketFd=socket(AF_INET,SOCK_STREAM,0))==-1)
        {
            perror("socket");
            return -1;
        }    
        printf("socket fd = %d
    ",socketFd);
        memset(&servAddr,0,sizeof(struct sockaddr_in));
        servAddr.sin_family = AF_INET;
        servAddr.sin_port   = htons(atoi(arg[2]));
        servAddr.sin_addr    = (*(struct in_addr *)host->h_addr);
        
        if(connect(socketFd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr))==-1)
        {
            perror("connect:");
            return -1;
        }
        
        while(1)
        {
            printf("input:");
            scanf("%s",buf);
            if(send(socketFd,buf,sizeof(buf),0)==-1)
            {
                perror("send:");
            }
            {
                printf("send successful!
    ");
            }
            memset(buf,0,sizeof(buf));
        }
        close(socketFd);
        return 0;
    }
     
  • 相关阅读:
    android 开发-自定义多节点进度条显示
    android开发 ,对接支付宝,服务器(PHP)校验失败
    android开发支付宝接口开发流程(密钥篇)
    android开发 解决启动页空白或黑屏问题
    关于的 recorder robotium 的Eclipse插件(URL:http://recorder.robotium.com/updates/或者说不可用)
    git android.google 源码:Unknown SSL protocol error in connection to code.google.com:443
    解决方案:android monkeyrunner:Timeout while trying to create chimp mananger(device = MonkeyRunner.waitForConnection()一直报错的问题)
    JasperReport学习札记6-JRXML的标签
    SQL Server 的动态语句(SQLServer 的String.format用法)(SQLServer的调用SQL占位符的使用)
    IReport5.6.0创建数据库连接找不到驱动(iReport中ClassNotFoundError错误的解决)
  • 原文地址:https://www.cnblogs.com/hanhuo/p/7586865.html
Copyright © 2011-2022 走看看