Reputation: 161
I'm currently having a problem passing messages between a server and client. As far as I know, I am properly following best practices for socket programming outlined by Beej's Socket Programming Tutorial.
When I run the two processes, the recv() syscall returns -1 (an error), rather than the number of bytes received. Also when trying to output the buf, there are a bunch of gobbledygook characters. Which makes sense, because of the error.
I'm wondering if someone could steer me in the right direction as to why I am having issues with recv()? The following are relevant code snippets.
Server:
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);
Client:
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;
The following is the output for 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æ
The following is the output for Client:
sockfd 4
5
Upvotes: 0
Views: 2175
Reputation: 3227
The sockfd
is just useed for listening the clients, newfd
is used for data transmitting.
Upvotes: 0
Reputation: 91099
Maybe I shouldn't write this as an answer, but as a comment. Nevertheless, IMHO your use of getaddrinfo()
seems wrong to me.
On the client side, it is supposed to be called and then iterated through the results until a connection can be established.
so
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
}
In this way, you can check all possible connections.
On the server side, it is rather unusual to use getaddrinfo()
. Normally, you would create an IPv6 socket and enable it to listen for IPv4 as well by using setsockopt()
to unset the IPV6_V6ONLY
flag. In this way, the socket listens to both IPv6 and IPv4. (Alas, not on WIndows XP AFAIK.)
Upvotes: 0
Reputation: 659
You want to recv() using the socket returned from accept()
byte_count = recv(newfd, buf, sizeof buf, 0);
Upvotes: 2
Reputation: 182664
You are calling recv
on the wrong socket. You need to recv
on newfd
:
byte_count = recv(newfd, buf, sizeof buf, 0); /* newfd instead of sockfd. */
Now that that's out of the way,
As far as I know, I am properly following best practices for socket programming
I completely disagree.
listen
, bind
, getaddrinfo
etcstrerror
or perror
in your programUpvotes: 7