home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / unix / programm / 5236 < prev    next >
Encoding:
Text File  |  1992-11-10  |  6.0 KB  |  221 lines

  1. Path: sparky!uunet!news.tek.com!psgrain!charnel!rat!usc!zaphod.mps.ohio-state.edu!darwin.sura.net!spool.mu.edu!hri.com!noc.near.net!ns.draper.com!news.draper.com!MVS.draper.com!SEB1525
  2. From: SEB1525@MVS.draper.com (Steve Bacher)
  3. Newsgroups: comp.unix.programmer
  4. Subject: UDP bidirectional socket problem
  5. Message-ID: <19921110153355SEB1525@MVS.draper.com>
  6. Date: 10 Nov 92 20:33:00 GMT
  7. Sender: MVS NNTP News Reader <NNMVS@MVS.draper.com>
  8. Organization: Draper Laboratory
  9. Lines: 209
  10. Nntp-Posting-Host: mvs.draper.com
  11.  
  12.  
  13. Please excuse me, those of you who saw this on comp.sys.sun.apps...
  14.  
  15. We have a program that sets up 2 UDP peer-to-peer sockets between two
  16. Suns.  If both Suns are Sun-3's, they can read and write between 2
  17. processes using 1 socket on each side.  If the Sun-3 talks to the Sparc,
  18. then single sockets don't work - you end up needing 4 sockets, 2 on each
  19. side, 1 read and 1 write.
  20.  
  21. Here is the program, along with 2 calling programs, to demonstrate the
  22. problem.  Each program takes the name of remote machine to talk to.
  23. You run sock1 on one host and subsequently sock2 on the other.
  24. sock1 writes a message to the other host, where sock2 reads it.
  25. Then sock2 reads a reply from the machine running sock1.
  26.  
  27. If I start sock1 on the sun4 and then start sock2 on the sun3,
  28. sock1 hangs waiting for sock2 to send it something.  sock2 appears
  29. never to return from the write to sock1.
  30.  
  31. If I start sock1 on the sun3 and then start sock2 on the sun4, sock1
  32. hangs and sock2 complains on the read because it did not block after the
  33. write.  No non-blocking has been specified.
  34.  
  35. We can get a message through if we disconnect the socket on 1 side.
  36. Executing the connect() call on the sun4 somehow screws things up.
  37.  
  38. Note that read() normally blocks.  sock1 does read() and waits and
  39. blocks just fine.  But if you have written to the socket, the first time
  40. you read from it it is nonblocking, so you have to force a loop to
  41. actually get it to block - the second one blocks.
  42.  
  43. I compared the output of the C preprocessor on the programs compiled on
  44. the sun3 and sun4.  The only significant difference is in the definition
  45. of the type physadr_t in /usr/include/sys/types.h, which is a struct
  46. containing a short on the sun-3 but a struct containing an int on a
  47. Sparc.  This doesn't seem to be used anywhere, though.
  48.  
  49. Here are the sample programs.
  50.  
  51. ------------------------------------------------------------------------
  52. makefile 
  53. ------------------------------------------------------------------------
  54.  
  55. sock1:          sock1.o sock.o
  56.                 cc -o sock1 sock1.o sock.o
  57.  
  58. sock2:          sock2.o sock.o
  59.                 cc -o sock2 sock2.o sock.o
  60.  
  61. sock.o:         recomp sock.c
  62.                 cc -c sock.c
  63.  
  64. sock1.o:        sock1.c
  65.                 cc -c sock1.c
  66.  
  67. sock2.o:        sock2.c
  68.                 cc -c sock2.c
  69.  
  70. recomp:
  71.                 -rm sock.o
  72.  
  73. ------------------------------------------------------------------------
  74. sock.c
  75. ------------------------------------------------------------------------
  76.  
  77. #include <sys/types.h>
  78. #include <sys/socket.h>
  79. #include <netinet/in.h>
  80. #include <netdb.h>
  81. #include <fcntl.h>
  82. #include <sys/types.h>
  83. #include <sys/time.h>
  84. #include <stdio.h>
  85. #define MAX_MLEN 128
  86. #define TRUE 1
  87. #define FALSE 0
  88.  
  89. int sock;
  90. char msg[MAX_MLEN];
  91.  
  92. set_socks(remote_host)
  93. char *remote_host;
  94. {
  95.   struct hostent *remote_ent;
  96.   unsigned long *remote_addr;
  97.   struct sockaddr_in remote_name,my_name;
  98.   int optval = TRUE;
  99.  
  100.   sock = socket(AF_INET, SOCK_DGRAM, 0);
  101.   if (sock < 0)
  102.   {
  103.     perror("Error opening socket ");
  104.     return(FALSE);
  105.   }
  106.  
  107.   my_name.sin_family = AF_INET;
  108.   my_name.sin_addr.s_addr = htonl(INADDR_ANY);
  109.   my_name.sin_port = htons(5002); /* write to me here */
  110.  
  111.   if (bind(sock, (struct sockaddr *) &my_name, sizeof(my_name)) < 0)
  112.   {
  113.     perror("Error binding my socket to my name");
  114.     return(FALSE);
  115.   }
  116.  
  117.   remote_ent = (struct hostent *) gethostbyname(remote_host);
  118.   remote_addr = (unsigned long *) remote_ent->h_addr;
  119.   remote_name.sin_family = AF_INET;
  120.   remote_name.sin_addr.s_addr = *remote_addr;
  121.   remote_name.sin_port = htons(5002);
  122.  
  123.   if(connect(sock, (struct sockaddr *) &remote_name,sizeof(remote_name)) < 0)
  124.   {
  125.     perror("Error connecting to remote port");
  126.     return(FALSE);
  127.   }
  128.   return(TRUE);
  129. }
  130.  
  131.  
  132. host2(sendto)
  133. char *sendto;
  134. {
  135. #define namelen 64
  136.   int i,j;
  137.   char me[namelen];
  138.   gethostname(me,namelen);
  139.   strcpy(msg,"Hello ");
  140.   strcat(msg, sendto);
  141.   strcat(msg, " Love, ");
  142.   strcat(msg,me);
  143.   strcat(msg,"\n");
  144.   printf("about to set socks on %s\n",me);
  145.   if(set_socks(sendto)){
  146.     printf("about to write the following message to %s ::\n",sendto);
  147.     printf("%s",msg);
  148.     if(write(sock,msg,MAX_MLEN)<0)
  149.     {
  150.       perror("write error");
  151.       return(FALSE);
  152.     }
  153.     j=0; 
  154.     while((i=read(sock,msg,MAX_MLEN)) < 0)
  155.     {
  156.       j += 1;
  157.       printf("read did not block after write\n");
  158.     }
  159.     printf(
  160.      "Got %d byte message from %s after %d read attempts. Msg: %s\n",
  161.             i,sendto,j,msg);
  162.   }
  163.   else exit(1);
  164. }
  165.  
  166. host1(sendto)
  167. char *sendto;
  168. {
  169. #define namelen 64
  170.   int i; 
  171.   char me[namelen];
  172.  
  173.   gethostname(me,namelen);
  174.   printf("about to set socks on %s\n",me);
  175.   if(set_socks(sendto)){
  176.     printf("about to wait for a message from %s ::\n",sendto);
  177.     i=read(sock,msg,MAX_MLEN);
  178.     printf("%s",msg);
  179.     strcpy(msg,"Bye ");
  180.     strcat(msg, sendto);
  181.     strcat(msg, " Love, ");
  182.     strcat(msg,me);
  183.     strcat(msg,"\n");
  184.     printf("about to send reply to %s\n", sendto);
  185.     sleep(2);
  186.     if(write(sock,msg,MAX_MLEN)<0)
  187.     {
  188.       perror("write error");
  189.     }
  190.   }
  191.   else exit(1);
  192.   close(sock);
  193. }
  194.  
  195. ------------------------------------------------------------------------
  196. sock1.c
  197. ------------------------------------------------------------------------
  198.  
  199. main(argc,argv)
  200. int argc;
  201. char **argv;
  202. {
  203.   host1(argv[1]);
  204. }
  205.  
  206. ------------------------------------------------------------------------
  207. sock2.c
  208. ------------------------------------------------------------------------
  209.  
  210. main(argc,argv)
  211. int argc;
  212. char **argv;
  213. {
  214.   host2(argv[1]);
  215. }
  216.  
  217.  
  218. --
  219. Steve Bacher (Batchman)                 Draper Laboratory
  220. Internet: seb@draper.com                Cambridge, MA, USA
  221.