首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++套接字recv()系统调用返回-1

C++套接字recv()系统调用返回-1
EN

Stack Overflow用户
提问于 2011-11-13 18:51:39
回答 4查看 1.9K关注 0票数 0

我目前在服务器和客户端之间传递消息时遇到问题。据我所知,我完全遵循了Beej's Socket Programming Tutorial概述的套接字编程的最佳实践。

当我运行这两个进程时,recv() syscall返回-1 (一个错误),而不是返回接收到的字节数。此外,当尝试输出buf时,有一堆官样文章字符。这是有道理的,因为这个错误。

我想知道是否有人可以引导我到正确的方向,为什么我在recv()上有问题?以下是相关的代码片段。

服务器:

代码语言:javascript
复制
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);

客户端:

代码语言:javascript
复制
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;

以下是服务器的输出:

代码语言:javascript
复制
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æ

以下是客户端的输出:

代码语言:javascript
复制
sockfd 4
5
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-13 18:54:34

您在错误的套接字上调用recv。你需要在newfd上使用recv

代码语言:javascript
复制
byte_count = recv(newfd, buf, sizeof buf, 0); /* newfd instead of sockfd. */

既然这样就没问题了,

据我所知,我完全遵循了套接字编程的最佳实践

我完全不同意。

  • 您没有检查listenbindgetaddrinfo等的返回状态
  • 您的程序中没有strerrorperror <代码>H215<代码>F216
票数 6
EN

Stack Overflow用户

发布于 2011-11-13 18:56:18

您希望使用从accept()返回的套接字recv()

代码语言:javascript
复制
byte_count  =  recv(newfd,  buf,  sizeof  buf,  0); 
票数 2
EN

Stack Overflow用户

发布于 2011-11-13 19:37:27

也许我不应该写这篇文章作为回答,而应该作为评论。尽管如此,我认为你使用getaddrinfo()是错误的。

  • 在客户端,它应该被调用,然后遍历结果,直到可以建立连接。

所以

struct addrinfo * r2 sockfd = -1;for (r2=res;r2;r2=r2->ai_ next ) { //创建套接字: if((sockfd =套接字(res->ai_family,res->ai_socktype,res->ai_protocol)) == -1){继续;//下一个结果} //尝试连接端口if(connect(sockfd,res->ai_addr,res->ai_addrlen) == -1){ close(sockfd);sockfd = -1;继续;}} if (sockfd == -1) { //做错误处理}

通过这种方式,你可以在服务器端检查所有可能的connections.

  • On,这是相当不寻常的使用getaddrinfo()。通常,您可以创建一个IPv6套接字,并通过使用setsockopt()取消设置IPV6_V6ONLY标志来使其能够侦听IPv4。通过这种方式,套接字同时监听IPv6和IPv4。(可惜,不是在WIndows XP AFAIK上。)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8111044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档