Actual source code: send.c

  1: #define PETSC_DLL
 2:  #include petsc.h
 3:  #include petscsys.h

  5: #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
  6: /* Some systems have inconsistent include files that use but do not
  7:    ensure that the following definitions are made */
  8: typedef unsigned char   u_char;
  9: typedef unsigned short  u_short;
 10: typedef unsigned short  ushort;
 11: typedef unsigned int    u_int;
 12: typedef unsigned long   u_long;
 13: #endif

 15: #include <errno.h>
 16: #if defined(PETSC_HAVE_STDLIB_H)
 17: #include <stdlib.h>
 18: #endif
 19: #include <sys/types.h>
 20: #include <ctype.h>
 21: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
 22: #include <machine/endian.h>
 23: #endif
 24: #if defined(PETSC_HAVE_UNISTD_H)
 25: #include <unistd.h>
 26: #endif
 27: #if defined(PETSC_HAVE_SYS_SOCKET_H)
 28: #include <sys/socket.h>
 29: #endif
 30: #if defined(PETSC_HAVE_SYS_WAIT_H)
 31: #include <sys/wait.h>
 32: #endif
 33: #if defined(PETSC_HAVE_NETINET_IN_H)
 34: #include <netinet/in.h>
 35: #endif
 36: #if defined(PETSC_HAVE_NETDB_H)
 37: #include <netdb.h>
 38: #endif
 39: #if defined(PETSC_HAVE_FCNTL_H)
 40: #include <fcntl.h>
 41: #endif
 42: #if defined(PETSC_HAVE_IO_H)
 43: #include <io.h>
 44: #endif
 45: #if defined(PETSC_HAVE_WINSOCK2_H)
 46: #include <Winsock2.h>
 47: #endif

 49:  #include ../src/sys/viewer/impls/socket/socket.h
 50: #include "petscfix.h"

 53: #if defined(PETSC_NEED_CLOSE_PROTO)
 55: #endif
 56: #if defined(PETSC_NEED_SOCKET_PROTO)
 58: #endif
 59: #if defined(PETSC_NEED_SLEEP_PROTO)
 61: #endif
 62: #if defined(PETSC_NEED_CONNECT_PROTO)
 64: #endif

 67: /*--------------------------------------------------------------*/
 70: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
 71: {
 72:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
 73:   PetscErrorCode     ierr;

 76:   if (vmatlab->port) {
 77: #if defined(PETSC_HAVE_CLOSESOCKET)
 78:     closesocket(vmatlab->port);
 79: #else
 80:     close(vmatlab->port);
 81: #endif
 82:     if (ierr) SETERRQ(PETSC_ERR_SYS,"System error closing socket");
 83:   }
 84:   PetscFree(vmatlab);
 85:   return(0);
 86: }

 88: /*--------------------------------------------------------------*/
 91: /*
 92:     PetscSocketOpen - handles connected to an open port where someone is waiting.

 94: .seealso:   SOCKAnswer_Private()
 95: */
 96: PetscErrorCode  PetscOpenSocket(char *hostname,int portnum,int *t)
 97: {
 98:   struct sockaddr_in sa;
 99:   struct hostent     *hp;
100:   int                s = 0;
101:   PetscErrorCode     ierr;
102:   PetscTruth         flg = PETSC_TRUE;

105:   if (!(hp=gethostbyname(hostname))) {
106:     perror("SEND: error gethostbyname: ");
107:     SETERRQ1(PETSC_ERR_SYS,"system error open connection to %s",hostname);
108:   }
109:   PetscMemzero(&sa,sizeof(sa));
110:   PetscMemcpy(&sa.sin_addr,hp->h_addr,hp->h_length);

112:   sa.sin_family = hp->h_addrtype;
113:   sa.sin_port = htons((u_short) portnum);
114:   while (flg) {
115:     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
116:       perror("SEND: error socket");  SETERRQ(PETSC_ERR_SYS,"system error");
117:     }
118:     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
119: #if defined(PETSC_HAVE_WSAGETLASTERROR)
120:       WSAGetLastError();
121:       if (ierr == WSAEADDRINUSE) {
122:         (*PetscErrorPrintf)("SEND: address is in use\n");
123:       } else if (ierr == WSAEALREADY) {
124:         (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
125:       } else if (ierr == WSAEISCONN) {
126:         (*PetscErrorPrintf)("SEND: socket already connected\n");
127:         Sleep((unsigned) 1);
128:       } else if (ierr == WSAECONNREFUSED) {
129:         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
130:         Sleep((unsigned) 1);
131:       } else {
132:         perror(NULL); SETERRQ(PETSC_ERR_SYS,"system error");
133:       }
134: #else
135:       if (errno == EADDRINUSE) {
136:         (*PetscErrorPrintf)("SEND: address is in use\n");
137:       } else if (errno == EALREADY) {
138:         (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
139:       } else if (errno == EISCONN) {
140:         (*PetscErrorPrintf)("SEND: socket already connected\n");
141:         sleep((unsigned) 1);
142:       } else if (errno == ECONNREFUSED) {
143:         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
144:         PetscInfo(0,"Connection refused in attaching socket, trying again");
145:         sleep((unsigned) 1);
146:       } else {
147:         perror(NULL); SETERRQ(PETSC_ERR_SYS,"system error");
148:       }
149: #endif
150:       flg = PETSC_TRUE;
151: #if defined(PETSC_HAVE_CLOSESOCKET)
152:       closesocket(s);
153: #else
154:       close(s);
155: #endif
156:     }
157:     else flg = PETSC_FALSE;
158:   }
159:   *t = s;
160:   return(0);
161: }

163: #define MAXHOSTNAME 100
164: /*-----------------------------------------------------------------*/
165: /* The listenport variable is an ugly hack. If the user hits a         */
166: /* control c while we are listening then we stop listening         */
167: /* but do not close the listen. Therefore if we try to bind again  */
168: /* and get an address in use, close the listen which was left      */
169: /* hanging; the problem is if the user uses several portnumbers    */
170: /* and control c we may not be able to close the correct listener. */
171: static int listenport;
174: static PetscErrorCode SOCKEstablish_Private(u_short portnum,int *ss)
175: {
176:   char               myname[MAXHOSTNAME+1];
177:   int                s;
178:   PetscErrorCode     ierr;
179:   struct sockaddr_in sa;
180:   struct hostent     *hp;
181:   int                optval = 1; /* Turn on the option */

184:   PetscGetHostName(myname,MAXHOSTNAME);

186:   PetscMemzero(&sa,sizeof(struct sockaddr_in));

188:   hp = gethostbyname(myname);
189:   if (!hp) SETERRQ(PETSC_ERR_SYS,"Unable to get hostent information from system");

191:   sa.sin_family = hp->h_addrtype;
192:   sa.sin_port = htons(portnum);

194:   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
195:     SETERRQ(PETSC_ERR_SYS,"Error running socket() command");
196:   }
197:   setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));

199:   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
200: #if defined(PETSC_HAVE_WSAGETLASTERROR)
201:     WSAGetLastError();
202:     if (ierr != WSAEADDRINUSE) {
203: #else
204:     if (errno != EADDRINUSE) {
205: #endif
206:       close(s);
207:       SETERRQ(PETSC_ERR_SYS,"Error from bind()");
208:     }
209:     close(listenport);
210:   }
211:   listen(s,0);
212:   *ss = s;
213:   return(0);
214: }

218: static PetscErrorCode SOCKAnswer_Private(int portnumber,int *t)
219: {
220:   PetscErrorCode     ierr;
221:   struct sockaddr_in isa;
222: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
223:   size_t             i;
224: #else
225:   int                i;
226: #endif

229: /* open port*/
230:   SOCKEstablish_Private((u_short) portnumber,&listenport);

232: /* wait for someone to try to connect */
233:   i = sizeof(struct sockaddr_in);
234:   if ((*t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
235:     SETERRQ(PETSC_ERR_SYS,"error from accept()\n");
236:   }
237:   close(listenport);
238:   return(0);
239: }

243: /*@C
244:    PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
245:         based server.

247:    Collective on MPI_Comm

249:    Input Parameters:
250: +  comm - the MPI communicator
251: .  machine - the machine the server is running on,, use PETSC_NULL for the local machine, use "server" to passively wait for
252:              a connection from elsewhere
253: -  port - the port to connect to, use PETSC_DEFAULT for the default

255:    Output Parameter:
256: .  lab - a context to use when communicating with the server

258:    Level: intermediate

260:    Notes:
261:    Most users should employ the following commands to access the 
262:    Matlab PetscViewers
263: $
264: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
265: $    MatView(Mat matrix,PetscViewer viewer)
266: $
267: $                or
268: $
269: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
270: $    VecView(Vec vector,PetscViewer viewer)

272:    Options Database Keys:
273:    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
274:    PETSC_VIEWER_SOCKET_() or if 
275:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
276: $    -viewer_socket_machine <machine>
277: $    -viewer_socket_port <port>

279:    Environmental variables:
280: +   PETSC_VIEWER_SOCKET_PORT portnumber
281: -   PETSC_VIEWER_SOCKET_MACHINE machine name

283:      Currently the only socket client available is Matlab. See 
284:      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.

286:    Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
287:           use PetscViewerBinaryRead/Write/GetDescriptor().

289:    Concepts: Matlab^sending data
290:    Concepts: sockets^sending data

292: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
293:           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, 
294:           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
295:           PetscBinaryViewerGetDescriptor()
296: @*/
297: PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
298: {

302:   PetscViewerCreate(comm,lab);
303:   PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);
304:   PetscViewerSocketSetConnection(*lab,machine,port);
305:   return(0);
306: }

310: PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
311: {
313:   PetscInt       def = -1;
314:   char           sdef[256];
315:   PetscTruth     tflg;

318:   /*
319:        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
320:     are listed here for the GUI to display
321:   */
322:   PetscOptionsHead("Socket PetscViewer Options");
323:     PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
324:     if (tflg) {
325:       PetscOptionsAtoi(sdef,&def);
326:     } else {
327:       def = PETSCSOCKETDEFAULTPORT;
328:     }
329:     PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);

331:     PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
332:     PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
333:     if (!tflg) {
334:       PetscGetHostName(sdef,256);
335:     }
336:   PetscOptionsTail();
337:   return(0);
338: }

343: PetscErrorCode  PetscViewerCreate_Socket(PetscViewer v)
344: {
345:   PetscViewer_Socket *vmatlab;
346:   PetscErrorCode     ierr;

349:   PetscNewLog(v,PetscViewer_Socket,&vmatlab);
350:   vmatlab->port          = 0;
351:   v->data                = (void*)vmatlab;
352:   v->ops->destroy        = PetscViewerDestroy_Socket;
353:   v->ops->flush          = 0;
354:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;

356:   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
357:   PetscObjectChangeTypeName((PetscObject)v,PETSC_VIEWER_BINARY);
358:   return(0);
359: }

364: /*@C
365:       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 
366:              viewer is to use

368:   Collective on PetscViewer

370:   Input Parameters:
371: +   v - viewer to connect
372: .   machine - host to connect to, use PETSC_NULL for the local machine,use "server" to passively wait for
373:              a connection from elsewhere
374: -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default

376:     Level: advanced

378: .seealso: PetscViewerSocketOpen()
379: @*/
380: PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],PetscInt port)
381: {
382:   PetscErrorCode     ierr;
383:   PetscMPIInt        rank;
384:   char               mach[256];
385:   PetscTruth         tflg;
386:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;

389:   if (port <= 0) {
390:     char portn[16];
391:     PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
392:     if (tflg) {
393:       PetscOptionsAtoi(portn,&port);
394:     } else {
395:       port = PETSCSOCKETDEFAULTPORT;
396:     }
397:   }
398:   if (!machine) {
399:     PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
400:     if (!tflg) {
401:       PetscGetHostName(mach,256);
402:     }
403:   } else {
404:     PetscStrncpy(mach,machine,256);
405:   }

407:   MPI_Comm_rank(((PetscObject)v)->comm,&rank);
408:   if (!rank) {
409:     PetscStrcmp(mach,"server",&tflg);
410:     if (tflg) {
411:       PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);
412:       SOCKAnswer_Private((int)port,&vmatlab->port);
413:     } else {
414:       PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
415:       PetscOpenSocket(mach,(int)port,&vmatlab->port);
416:     }
417:   }
418:   return(0);
419: }

421: /* ---------------------------------------------------------------------*/
422: /*
423:     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
424:   is attached to a communicator, in this case the attribute is a PetscViewer.
425: */
426: static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;


431: /*@C
432:      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.

434:      Collective on MPI_Comm

436:      Input Parameter:
437: .    comm - the MPI communicator to share the socket PetscViewer

439:      Level: intermediate

441:    Options Database Keys:
442:    For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD or if 
443:     PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
444: $    -viewer_socket_machine <machine>
445: $    -viewer_socket_port <port>

447:    Environmental variables:
448: +   PETSC_VIEWER_SOCKET_PORT portnumber
449: -   PETSC_VIEWER_SOCKET_MACHINE machine name

451:      Notes:
452:      Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return 
453:      an error code.  The socket PetscViewer is usually used in the form
454: $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));

456:      Currently the only socket client available is Matlab. See 
457:      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.

459:      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.

461: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
462:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
463:           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor()
464: @*/
465: PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
466: {
468:   PetscTruth     flg;
469:   PetscViewer    viewer;

472:   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
473:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
474:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
475:   }
476:   MPI_Attr_get(comm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int*)&flg);
477:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
478:   if (!flg) { /* PetscViewer not yet created */
479:     PetscViewerSocketOpen(comm,0,0,&viewer);
480:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
481:     PetscObjectRegisterDestroy((PetscObject)viewer);
482:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
483:     MPI_Attr_put(comm,Petsc_Viewer_Socket_keyval,(void*)viewer);
484:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
485:   }
486:   PetscFunctionReturn(viewer);
487: }