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

标签 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;
}

最佳答案

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

  • 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);
}

关于c - TCP 服务器在第一次连接后挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44987062/

相关文章:

与 C 中的 typedef 和指针混淆

sockets - Ruby 中的 TCPServer.new(port) 和 TCPServer.open ("X.X.X.X", port) 有什么区别?

c++ - 文件 I/O - 显示文件的内容

c++ - 为 tcp 服务器 c++ 正确声明缓冲区

c - 问题中函数无法返回 returnSize 数组中的元素

c - c中的迭代目录遍历

iphone - 如何从服务器(而非 Web 服务器)最好地为 >10,000 个 iPhone 客户端提供服务

ssl - ECDHE 客户端如何发送Pre Master secret

c - 使用C语言中的套接字向FTP服务器发送命令

c - 在C中查找重复项