hubert@spica.ucsb.edu (05/14/91)
Hi! I am testing the socket's datagram facility and I can't figure out why the following program doesn't work. The a.out give me error message like "bad address". Could someone explain it ? By the way, I just want to use these system call instead of the listen ,accept and connect for the socket_stream. Thanks. #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> main() { int s1,s2,ret; char mesg0[20],mesg1[20],mesg2[20],mesg3[20],mesg4[20]; struct sockaddr sock1,sock2; sock1.sa_family=PF_UNIX; sock2.sa_family=PF_UNIX; sprintf(sock1.sa_data,"sock1"); sprintf(sock2.sa_data,"sock2"); unlink(sock1.sa_data); unlink(sock2.sa_data); if ((s2=socket(PF_UNIX, SOCK_DGRAM,0)) == -1) perror("child socket creating error \n"); if (bind(s2, &sock2,sizeof(sock2))==-1) perror("child binding eror\n"); if ((s1=socket(PF_UNIX, SOCK_DGRAM,0)) == -1) perror("parent socket creating error \n"); if (bind(s1, &sock1,sizeof(sock1))==-1) perror("parent binding eror\n"); sprintf(mesg0,"first"); if (sendto(s1, mesg0, sizeof(mesg0),0, &sock2,sizeof(sock2))==-1) perror("parent send error\n"); if (fork()==0) { printf("child birth\n"); if (recvfrom(s2, mesg2, sizeof(mesg2),0,&sock1,sizeof(sock1))==-1) perror("child receive error\n"); printf("child receives mesg %s\n",mesg2); sprintf(mesg3,"child's messag"); if (sendto(s2, mesg3, sizeof(mesg3),0, &sock1,sizeof(sock1))==-1) perror("send error\n"); exit(0); } printf("mother\n"); if (recvfrom(s1, mesg4, sizeof(mesg4),0,&sock2, sizeof(sock2))==-1) perror("receive error\n"); printf("%s\n",mesg2); wait(&ret); unlink(sock1.sa_data); unlink(sock2.sa_data); if (close(s1)==-1) perror("close error\n"); if (close(s2)==-1) perror("close error\n"); } -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hung-Hsien Chang ( Hubert) E-mail: hubert@cs.ucsb.edu P.S: Hubert is not my middle name; it is easier for American friends to call me.
net@opal.cs.tu-berlin.de (Oliver Laumann) (05/14/91)
In article <11225@hub.ucsb.edu> hubert@spica.ucsb.edu writes: > Hi! I am testing the socket's datagram facility and I can't figure > out why the following program doesn't work. The a.out give me > error message like "bad address". Could someone explain it ? > > if (recvfrom(s1, mesg4, sizeof(mesg4),0,&sock2, sizeof(sock2))==-1) > perror("receive error\n"); The last argument of recvfrom() is of type int*, not just int (it's an input-output parameter). You initialize it with the size of the buffer that will be filled with the address; recvfrom() fills it with the actual size of the address stored in the buffer on return. To fix your program, declare an additional int variable "fromlen" and invoke recvfrom() like this: fromlen = sizeof(sock2); if (recvfrom(...,&sock2,&fromlen) ... -- Oliver Laumann net@tub.cs.tu-berlin.de net@tub.UUCP ol@gnu.ai.mit.edu
subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (05/14/91)
In article <11225@hub.ucsb.edu> hubert@spica.ucsb.edu writes: > >Hi! I am testing the socket's datagram facility and I can't figure >out why the following program doesn't work. The a.out give me >error message like "bad address". Could someone explain it ? > >By the way, I just want to use these system call instead of >the listen ,accept and connect for the socket_stream. [lotsa code deleted] The reason you're getting bad addresses is because you're specifying a variable, rather than the address of a variable, for the last parameter fromlen. You say: recvfrom(s2, mesg2, sizeof(mesg2), 0, &sock1, sizeof(sock1)); The "sizeof(sock1)" should be some variable where it STORES the size of the address that it receives data from. While passing "&sock1", you say that that is the place to store the address of the next datagram that you receive. While this is okay in this hackish example because that's the only sockaddr whose socket you're going to get data from, I don't think you understand the purpose of those parameters. You cannot say "I want to receive the next datagram from sockaddr foo, and you please fill it in". recvfrom() just returns the next datagram being sent to the specified socket; if you want to know who sent it to you, you should create another struct sockaddr and pass its address, rather than &sock1. Again, if you want to know the size of that address, you create another variable, and pass its address in fromlen. Here's an example of what I think you were trying to illustrate (with some error checking deleted): #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> main() { int s1, s2, len, sz; char mesgp[20], mesgc[20], mesgt[20]; struct sockaddr sock1, sock2, stemp; sock1.sa_family=PF_UNIX; sock2.sa_family=PF_UNIX; sprintf(sock1.sa_data,"sock1"); sprintf(sock2.sa_data,"sock2"); unlink(sock1.sa_data); unlink(sock2.sa_data); s2 = socket(PF_UNIX, SOCK_DGRAM,0); bind(s2, &sock2,sizeof(sock2)); s1 = socket(PF_UNIX, SOCK_DGRAM,0); bind(s1, &sock1,sizeof(sock1)); sprintf(mesgt,"first"); /* actually don't need a variable for this */ if (sendto(s1, mesgt, sizeof(mesgt), 0, &sock2,sizeof(sock2))==-1) perror("parent send error"); if (! fork()) { printf("child\n"); if (recvfrom(s2, mesgc, sizeof(mesgc), 0, &stemp, &sz)==-1) perror("child receive error"); else printf("child receives mesg %s\n", mesgc); sprintf(mesgt,"second"); if (sendto(s2, mesgt, sizeof(mesgt),0, &sock1, sizeof(sock1)) == -1) perror("child send error"); exit(0); } printf("parent\n"); if (recvfrom(s1, mesgp, sizeof(mesgp), 0, &stemp, &sz) == -1) perror("parent receive error"); else printf("got this from kid: %s\n",mesgp); wait(0); unlink(sock1.sa_data); unlink(sock2.sa_data); } Aren't datagram sockets fun? :-) -Kartik -- internet% ypwhich subbarao@phoenix.Princeton.EDU -| Internet kartik@silvertone.Princeton.EDU (NeXT mail) SUBBARAO@PUCC.BITNET - Bitnet