簡體   English   中英

C ++套接字recv()syscall返回-1

[英]C++ Sockets recv() syscall returning -1

我目前在服務器和客戶端之間傳遞消息時遇到問題。 據我所知,我正確地遵循了Beej的Socket Programming Tutorial中概述的套接字編程最佳實踐。

當我運行兩個進程時,recv()syscall返回-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;

以下是服務器的輸出:

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

您在錯誤的套接字上調用recv 你需要recvnewfd

byte_count = recv(newfd, buf, sizeof buf, 0); /* newfd instead of sockfd. */

既然這樣了,

據我所知,我正確地遵循了套接字編程的最佳實踐

我完全不同意。

  • 您沒有檢查listenbindgetaddrinfo等的返回狀態
  • 有沒有strerrorperror在你的程序

您想使用accept()返回的套接字來接收recv()

byte_count  =  recv(newfd,  buf,  sizeof  buf,  0); 

sockfd僅用於偵聽客戶端, newfd用於數據傳輸。

也許我不應該將此作為答案,而應作為評論。 不過,恕我直言,您對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()非常不尋常。 通常,您可以通過使用setsockopt()取消設置IPV6_V6ONLY標志來創建一個IPv6套接字,並使它也可以偵聽IPv4。 這樣,套接字可以偵聽IPv6和IPv4。 (A,不是在Windows XP XP AFAIK上。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM