第一次连接后TCP服务器挂起

时间:2017-07-08 13:59:12

标签: c networking tcpserver

我正在实现一个简单的TCP回显服务器,它回写写入它的任何内容。当我第一次向它发送一些数据时,使用telnet连接到它,它被发送回(预期)但之后挂起我假设没有发回任何东西。

这是我的代码(man getaddrinfo中的示例的一个小修改版本)。下面我recv()send()的方式有什么问题吗?

#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>


#define MAX_LISTEN_BACKLOG 1
#define BUFFER_SIZE 4096

int main(int argc, char* argv[]){   
    char buf[BUFFER_SIZE];
    int sfd,n,s;
    struct addrinfo hints;
    struct addrinfo *result;
    struct addrinfo *rp;
    struct sockaddr_storage peer_addr;
    socklen_t peer_addr_len;
    ssize_t nread;
    int addr_info_error;


    memset(&hints,0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    hints.ai_protocol = 0;
    hints.ai_canonname = NULL;
    hints.ai_addr = NULL;
    hints.ai_next = NULL;

    s = getaddrinfo(NULL, argv[1], &hints, &result);
    if (s != 0){
        printf("got error getaddrinfo");
    }

    for( rp = result; rp !=NULL; rp = rp->ai_next){
      sfd = socket(rp->ai_family,rp->ai_socktype,rp->ai_protocol);
      if (sfd == -1) perror("could not create socket");
      if (bind(sfd,rp->ai_addr,rp->ai_addrlen) == 0 ) break;
      close(sfd);
    }

    if (rp == NULL){
        perror("could not bind");
    }
    freeaddrinfo(result);
    int nsfd;
    listen(sfd,100);


    for(;;){

        peer_addr_len = sizeof(struct sockaddr_storage);
        nsfd = accept(sfd,(struct sockaddr*) &peer_addr_len,&peer_addr_len);
        nread = recv(nsfd,buf,BUFFER_SIZE,0);
        if(nread == -1)
            continue;
        printf("got ...%d",nread); // this line never prints?????
        char host[NI_MAXHOST], service[NI_MAXSERV];
        s = getnameinfo((struct sockaddr*) &peer_addr,
                peer_addr_len,host,NI_MAXHOST,
                service,NI_MAXSERV,NI_NUMERICSERV);

        if (s == 0) printf("recieved %s bytes from host:%s port:%s",nread,host,service);
        else printf("got %d in s",s); 
        if(send(nsfd,buf,nread,0) != nread)
            perror("error sending response");
    }
return 0;
}

1 个答案:

答案 0 :(得分:-2)

[本文适用于无法阅读代码的人]

  • accept()成功后添加额外的循环。一旦连接终止,此循环结束。
  • 在read()返回-1
  • 后检查errno
  • 诊断输出应该转到stderr,而不是stdout。
for(;;){

    peer_addr_len = sizeof(struct sockaddr_storage);
    nsfd = accept(sfd,(struct sockaddr*) &peer_addr_len,&peer_addr_len);
    if (nsfd ==-1) {perror("error sending response"); break; }

    for(;;) {
            nread = recv(nsfd,buf,BUFFER_SIZE,0);
            fprintf(stderr, "got ...%d",nread);
            if(nread == -1){
                    if(errno==EAGAIN) continue;
                    else break;
                    }
            if(nread == 0) break;

            char host[NI_MAXHOST], service[NI_MAXSERV];
            s = getnameinfo((struct sockaddr*) &peer_addr,
                    peer_addr_len,host,NI_MAXHOST,
                    service,NI_MAXSERV,NI_NUMERICSERV);

            if (s == 0) fprintf(stderr
                    , "received %s bytes from host:%s port:%s\n"
                    , nread,host,service);
            else fprintf(stderr, "got %d in s\n", s);

            if(send(nsfd,buf,nread,0) != nread) {
                    perror("error sending response");
                    break;
                    }

    }
    close(nsfd);
}