[comp.unix.wizards] Socket datagram

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