我目前在服务器和客户端之间传递消息时遇到问题。 据我所知,我正在遵循Beej's Socket Programming Tutorial概述的套接字编程的最佳实践。
当我运行这两个进程时,recv()系统调用返回-1(错误),而不是接收的字节数。此外,当尝试输出buf时,有一堆gobbledygook字符。这是有道理的,因为错误。
我想知道是否有人可以引导我朝着正确的方向指导我为什么遇到recv()的问题?以下是相关的代码片段。
服务器:
struct sockaddr_storage their_addr;
socklen_t addr_size;
int sockfd, newfd, byte_count, status;
char buf[512];
struct addrinfo hints, *res;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// get address info, print stuff if error
if((status = getaddrinfo("nunki.usc.edu", "21957", &hints, &res)) !=0){
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
// make a socket:
if((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1){
cout << "socket fail" << endl;
}
// bind the socket to the port
bind(sockfd, res->ai_addr, res->ai_addrlen);
// required output
cout << "Phase1: Login server has TCP port number " << "21957 "
<< "and IP address " << getIPfromHost("nunki.usc.edu") << endl;
// listen for incoming connections
listen(sockfd, 10);
cout << "after listen" << endl;
// halt until receipt
addr_size = sizeof(their_addr);
newfd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
cout << "after accept" << endl;
// Now that we're connected, we can receive some data
byte_count = recv(sockfd, buf, sizeof buf, 0);
printf("recv()'d %d bytes of data in buf\n", byte_count);
printf("Msg is %s\n", buf);
客户端:
struct addrinfo hints, *res;
int sockfd;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("nunki.usc.edu", "21957", &hints, &res);
// make a socket:
if((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1){
cout << "socket fail" << endl;
}
// attempt connection to port
if(connect(sockfd, res->ai_addr, res->ai_addrlen) == -1){
cout << "connect fail" << endl;
}
// send message to server
cout << "sockfd " << sockfd << endl;
int byte_count = send(sockfd, "Hello", 5, 0);
cout << byte_count << endl;
以下是Server的输出:
Phase1: Login server has TCP port number 21957 and IP address 68.181.201.3
after listen
after accept
recv()'d -1 bytes of data in buf
Msg is ÿhÿ?sÈ
Glæ
以下是客户的输出:
sockfd 4
5
答案 0 :(得分:6)
您正在错误的套接字上调用recv
。您需要recv
上的newfd
:
byte_count = recv(newfd, buf, sizeof buf, 0); /* newfd instead of sockfd. */
现在已经不在了,
据我所知,我正在遵循套接字的最佳做法 编程
我完全不同意。
listen
,bind
,getaddrinfo
等的返回状态strerror
或perror
答案 1 :(得分:2)
你想使用从accept()
返回的套接字来recv()byte_count = recv(newfd, buf, sizeof buf, 0);
答案 2 :(得分:0)
也许我不应该将此作为答案,而是作为评论。然而,恕我直言,你使用getaddrinfo()
似乎对我不利。
在客户端,它应该被调用然后遍历结果,直到建立连接。
所以
struct addrinfo * r2
sockfd = -1;
for (r2=res; r2; r2=r2->ai_next) {
// make a socket:
if((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1){
continue; // next result
}
// attempt connection to port
if(connect(sockfd, res->ai_addr, res->ai_addrlen) == -1){
close(sockfd);
sockfd = -1;
continue;
}
}
if (sockfd == -1) {
// do error handling
}
通过这种方式,您可以检查所有可能的连接。
在服务器端,使用getaddrinfo()
是相当不寻常的。通常,您将创建一个IPv6套接字并使其能够通过使用setsockopt()
取消设置IPV6_V6ONLY
标志来监听IPv4。通过这种方式,套接字可以同时监听IPv6和IPv4。 (唉,不是在WIndows XP AFAIK上。)
答案 3 :(得分:0)
sockfd
仅用于侦听客户端,newfd
用于数据传输。