1. 程式人生 > >解決Linux 下server和client 通過TCP通訊:accept成功接收卻報錯的問題

解決Linux 下server和client 通過TCP通訊:accept成功接收卻報錯的問題

ipv4 socket error 實例代碼 ... lis col argc 例子

  今天在寫簡單的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!\r\n"); 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\n",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 \r\n"); 50 } 51 52 if(listen(socketFd,BACKLOG)==-1) 53 { 54 perror("listen:"); 55 } 56 else 57 { 58 printf("Listening...\r\n"); 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!\r\n"); 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\r\n",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!\r\n");
        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\n",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!\r\n");
        }
        memset(buf,0,sizeof(buf));
    }
    close(socketFd);
    return 0;
}

 

解決Linux 下server和client 通過TCP通訊:accept成功接收卻報錯的問題