【发布时间】:2017-07-09 00:15:42
【问题描述】:
我正在实现一个简单的 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;
}
【问题讨论】:
-
printf("got ...%d",nread); // this line never prints????:在消息中添加“\n”。(并且诊断输出应该转到stderr) -
1) 因为 stdout 是 行缓冲 2) 因为你在循环中第二次阻塞了 accept()。
-
我通过将接受移出循环来让它工作
-
关于:
printf("got error getaddrinfo");错误文本应该输出到stderr,而不是stdout。建议:perror("getaddrinfo failed");这是清理的好时机,然后致电exit( EXIT_FAILURE ); -
关于:
if (sfd == -1) perror("could not create socket"); if (bind(sfd,rp->ai_addr,rp->ai_addrlen) == 0 ) break;1) 为什么打电话给break;? 2)当socket()失败时,不要尝试bind()那个(不存在的)socket
标签: c networking tcpserver