Error in send and recv(). Please help. - Unix
This is a discussion on Error in send and recv(). Please help. - Unix ; I wrote a client and server program in C. The server is actually IPv6
socket and client is IPv4. They both use the storage structure
sockaddr_storage to cast to IPv6 and IPv4.
The client and server are connected but the ...
-
Error in send and recv(). Please help.
I wrote a client and server program in C. The server is actually IPv6
socket and client is IPv4. They both use the storage structure
sockaddr_storage to cast to IPv6 and IPv4.
The client and server are connected but the server cannot send the
data to the client. I am pasting the code. Do you see any obvious
mistake in the code.
Please help. Every help is greatly appreciated.
Thanks.
I compiled the code using gcc -client.c -o client and gcc server.c -o
server, and then running the ./server and ./client 127.0.0.1.
***********Server Code*******************
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 3500
#define LISTEN_COUNT 5
#define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46
int main()
{
int sockfd, new_fd;
char str[INET6_ADDRSTRLEN];
/* Storage struct */
struct sockaddr_storage my_addr, their_addr;
/* IPv6 struct */
struct sockaddr_in6 *in6;
struct sockaddr_in6 *in6their;
socklen_t my_addrlen = sizeof(my_addr);
socklen_t their_addrlen = sizeof(their_addr);
printf("\n Length of my_addr = %d\n", my_addrlen);
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
if (sockfd == -1){
printf("\n Error creating socket");
exit(1);
}
/* Casting Storage to IPv6 */
in6 = (struct sockaddr_in6 *) &my_addr;
/* Populating Values */
// (*in6).sin6_len = sizeof(struct sockaddr_in6);
(*in6).sin6_family = AF_INET6;
(*in6).sin6_port = htons(PORT);
(*in6).sin6_addr = in6addr_any; //loopback;
/* binding */
if ( (bind(sockfd, (struct sockaddr *) &my_addr, my_addrlen) == -1) )
{
printf("\n Can't bind");
exit(1);
}
/* Listening */
if (listen(sockfd, LISTEN_COUNT) == -1) {
printf("\n Error( listening");
exit(1);
}
printf("\n Server: I am listening\n");
/* Accept, Print and Send back through another child process */
while (1){
if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
&their_addrlen) == -1) ){
printf("\n Can't accept");
continue;
}
/* Casting Storage to IPv4 */
in6their = (struct sockadd_in6 *) &their_addr;
printf("\n Server got connection from %s\n", inet_ntop(AF_INET6,
&( (*in6their).sin6_addr), str, sizeof(str) ) );
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
printf("Error sending");
close(new_fd);
exit(0);
}
}
close(new_fd); // parent doesn't need this
}
return 0;
}
***********Client Code*******************
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 3500
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct sockaddr_storage my_addr;
struct hostent *he;
struct sockaddr_in *in4;
if (argc != 2){
printf("\n Incorrect usage\n");
}
if ( (he=gethostbyname2(argv[1], AF_INET) ) == NULL ) {
printf("\n Error in gethostbyname\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1){
printf("\n Error creating socket\n");
exit(1);
}
in4 = (struct sockaddr_in *) &my_addr;
(*in4).sin_family = AF_INET;
(*in4).sin_port = htons(PORT);
(*in4).sin_addr = *((struct in_addr *) he->h_addr);
memset((*in4).sin_zero, '\0', sizeof((*in4).sin_zero) );
if ( connect(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) ==
-1) {
printf("\n Error Connecting\n");
exit(1);
}
printf("\n Client: I have been connected\n");
if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1,0)) == -1) {
printf("\n Error recieving\n");
exit(1);
}
printf("\n Client: I have received data\n");
buf[numbytes] = '\0';
printf("\n Received: %s\n", buf);
close(sockfd);
return 0;
}
-
Re: Error in send and recv(). Please help.
In article
<726df89a-0bd9-48db-8a53-33ad220f00e4@c22g2000prc.googlegroups.com>,
DanielJohnson wrote:
> I wrote a client and server program in C. The server is actually IPv6
> socket and client is IPv4. They both use the storage structure
> sockaddr_storage to cast to IPv6 and IPv4.
>
> The client and server are connected but the server cannot send the
> data to the client. I am pasting the code. Do you see any obvious
> mistake in the code.
What error is it getting? You should use perror() rather than just
printing "Error sending".
>
> Please help. Every help is greatly appreciated.
>
> Thanks.
>
>
> I compiled the code using gcc -client.c -o client and gcc server.c -o
> server, and then running the ./server and ./client 127.0.0.1.
>
> ***********Server Code*******************
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
>
> #define PORT 3500
> #define LISTEN_COUNT 5
> #define INET_ADDRSTRLEN 16
> #define INET6_ADDRSTRLEN 46
>
>
> int main()
> {
> int sockfd, new_fd;
>
> char str[INET6_ADDRSTRLEN];
>
> /* Storage struct */
> struct sockaddr_storage my_addr, their_addr;
>
> /* IPv6 struct */
> struct sockaddr_in6 *in6;
> struct sockaddr_in6 *in6their;
>
> socklen_t my_addrlen = sizeof(my_addr);
> socklen_t their_addrlen = sizeof(their_addr);
>
> printf("\n Length of my_addr = %d\n", my_addrlen);
>
> sockfd = socket(AF_INET6, SOCK_STREAM, 0);
> if (sockfd == -1){
> printf("\n Error creating socket");
> exit(1);
> }
>
> /* Casting Storage to IPv6 */
> in6 = (struct sockaddr_in6 *) &my_addr;
>
> /* Populating Values */
> // (*in6).sin6_len = sizeof(struct sockaddr_in6);
> (*in6).sin6_family = AF_INET6;
> (*in6).sin6_port = htons(PORT);
> (*in6).sin6_addr = in6addr_any; //loopback;
>
> /* binding */
> if ( (bind(sockfd, (struct sockaddr *) &my_addr, my_addrlen) == -1) )
> {
> printf("\n Can't bind");
> exit(1);
> }
>
> /* Listening */
> if (listen(sockfd, LISTEN_COUNT) == -1) {
> printf("\n Error( listening");
> exit(1);
> }
>
> printf("\n Server: I am listening\n");
>
> /* Accept, Print and Send back through another child process */
> while (1){
> if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
> &their_addrlen) == -1) ){
> printf("\n Can't accept");
> continue;
> }
> /* Casting Storage to IPv4 */
> in6their = (struct sockadd_in6 *) &their_addr;
>
>
> printf("\n Server got connection from %s\n", inet_ntop(AF_INET6,
> &( (*in6their).sin6_addr), str, sizeof(str) ) );
>
> if (!fork()) { // this is the child process
> close(sockfd); // child doesn't need the listener
> if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
> printf("Error sending");
> close(new_fd);
> exit(0);
> }
> }
>
> close(new_fd); // parent doesn't need this
> }
>
> return 0;
> }
>
>
> ***********Client Code*******************
>
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
>
> #define PORT 3500
> #define MAXDATASIZE 100
>
> int main(int argc, char *argv[])
> {
>
> int sockfd, numbytes;
> char buf[MAXDATASIZE];
>
> struct sockaddr_storage my_addr;
> struct hostent *he;
>
> struct sockaddr_in *in4;
>
> if (argc != 2){
> printf("\n Incorrect usage\n");
> }
>
>
> if ( (he=gethostbyname2(argv[1], AF_INET) ) == NULL ) {
> printf("\n Error in gethostbyname\n");
> exit(1);
> }
>
> sockfd = socket(AF_INET, SOCK_STREAM, 0);
> if (sockfd == -1){
> printf("\n Error creating socket\n");
> exit(1);
> }
>
> in4 = (struct sockaddr_in *) &my_addr;
>
> (*in4).sin_family = AF_INET;
> (*in4).sin_port = htons(PORT);
> (*in4).sin_addr = *((struct in_addr *) he->h_addr);
>
> memset((*in4).sin_zero, '\0', sizeof((*in4).sin_zero) );
>
> if ( connect(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) ==
> -1) {
> printf("\n Error Connecting\n");
> exit(1);
> }
>
> printf("\n Client: I have been connected\n");
>
> if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1,0)) == -1) {
> printf("\n Error recieving\n");
> exit(1);
> }
>
> printf("\n Client: I have received data\n");
>
>
> buf[numbytes] = '\0';
> printf("\n Received: %s\n", buf);
>
> close(sockfd);
>
> return 0;
>
> }
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
-
Re: Error in send and recv(). Please help.
On Wed, 24 Sep 2008 13:13:14 -0700 (PDT),
DanielJohnson wrote:
> /* Accept, Print and Send back through another child process */
> while (1){
> if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
> &their_addrlen) == -1) ){
[...]
> if (!fork()) { // this is the child process
> close(sockfd); // child doesn't need the listener
> if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
new_fd is not a socket. It's a file descriptor. Use write(new_fd,...)
instead of send.
Martien
--
|
Martien Verbruggen | "In a world without fences,
| who needs Gates?"
|
-
Re: Error in send and recv(). Please help.
DanielJohnson wrote:
>I wrote a client and server program in C. The server is actually IPv6
>socket and client is IPv4. They both use the storage structure
>sockaddr_storage to cast to IPv6 and IPv4.
Before I begin, I'm going to take this opportunity to say that I've
recently updated Beej's Guide to Network Programming (a decade-old
document) to include IPv6 stuff.
It's got a lot of new and changed material, and I'm sure I have more
than my fair share of mistakes in it, but I'd surely appreciate
suggestions from the lot of you Unixy-types...
http://beej.us/guide/bgnet/
>Do you see any obvious mistake in the code.
The dealbreaker isn't obvious, but it's a classic C mistake. There are
a few other things, too.
>I compiled the code using gcc -client.c -o client and gcc server.c -o
>server, and then running the ./server and ./client 127.0.0.1.
Use -Wall when compiling; it'll catch more errors, like this:
$ cc -Wall -o server server.c
server.c: In function 'main':
server.c:73: warning: assignment from incompatible pointer type
Ok, let's go!
>***********Server Code*******************
> sockfd = socket(AF_INET6, SOCK_STREAM, 0);
> if (sockfd == -1){
> printf("\n Error creating socket");
use perror("socket") here--it'll tell you the error. In fact, perror()
will work for you everywhere except for gethostbyname() and
getaddrinfo(), pretty much.
> (*in6).sin6_family = AF_INET6;
More readable C shorthand for the above line is:
in6->sin6_family = AF_INET6;
> (*in6).sin6_addr = in6addr_any; //loopback;
This isn't actually the loopback address, necessarily. It's any address
on this host. (Compare to in6addr_loopback.)
> if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
>&their_addrlen) == -1) ){
There it is, the classic C error. What's wrong? Parenthesis mismatch.
The comparison between accept() and -1 is taking place first, resulting
in false (0), which is then assigned into new_fd every time. You want
this:
if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
&their_addrlen) ) == -1 ){
^ ^
Using perror() on that line told me "send: Socket operation on
non-socket". Which got me thinking about why new_fd wasn't a socket
when it was clearly returned by accept(). It was getting set to 0, as
we saw above, and file descriptor 0 is stdin, which is not a socket. So
it all makes sense.
> in6their = (struct sockadd_in6 *) &their_addr;
There's the warning. struct sockadd_in6 (missing an "r") is not the
type of in6their. It's a cast to a pointer of an incomplete type, but
not one that has been declared--I'm a little surprised the compiler
didn't complain more about this.
> if (!fork()) { // this is the child process
> close(sockfd); // child doesn't need the listener
> if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
> printf("Error sending");
> close(new_fd);
> exit(0);
> }
exit(0); // exit here! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
> }
You need to exit the child process, or else it'll loop back around and
try to accept() along with the parent. You don't want that.
>****************Client Code*******************
> if (argc != 2){
> printf("\n Incorrect usage\n");
exit(1); // <<<<<<<<<<<<<<<<<<
> }
You probably don't want to keep running in that case.
> memset((*in4).sin_zero, '\0', sizeof((*in4).sin_zero) );
You should #include for memset(). Also, I've heard that
setting sin_zero to zero isn't strictly necessary, but I haven't seen
the definitive answer.
I think that's all I changed...hopefully that'll get it going.
HTH!
-Beej
-
Re: Error in send and recv(). Please help.
In article ,
Martien Verbruggen wrote:
> On Wed, 24 Sep 2008 13:13:14 -0700 (PDT),
> DanielJohnson wrote:
>
>
> > /* Accept, Print and Send back through another child process */
> > while (1){
> > if ( (new_fd = accept(sockfd, (struct sockaddr *) &their_addr,
> > &their_addrlen) == -1) ){
>
> [...]
>
> > if (!fork()) { // this is the child process
> > close(sockfd); // child doesn't need the listener
> > if (send(new_fd, "Hello World", sizeof("Hello World"), 0) == -1) {
>
> new_fd is not a socket. It's a file descriptor. Use write(new_fd,...)
> instead of send.
Wrong, it's a file descriptor that refers to a socket. Accept() always
returns a socket file descriptor.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
-
Re: Error in send and recv(). Please help.
Thanks for all the replies. It helped me figure out and I was able to
run the program.