Actual source code: send.c

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

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

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

 48:  #include ../src/sys/viewer/impls/socket/socket.h

 51: #if defined(PETSC_NEED_CLOSE_PROTO)
 53: #endif
 54: #if defined(PETSC_NEED_SOCKET_PROTO)
 56: #endif
 57: #if defined(PETSC_NEED_SLEEP_PROTO)
 59: #endif
 60: #if defined(PETSC_NEED_CONNECT_PROTO)
 62: #endif

 65: /*--------------------------------------------------------------*/
 68: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
 69: {
 70:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
 71:   PetscErrorCode     ierr;

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

 86: /*--------------------------------------------------------------*/
 89: /*
 90:     PetscSocketOpen - handles connected to an open port where someone is waiting.

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

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

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

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

182:   PetscGetHostName(myname,MAXHOSTNAME);

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

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

189:   sa.sin_family = hp->h_addrtype;
190:   sa.sin_port = htons(portnum);

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

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

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

227: /* open port*/
228:   SOCKEstablish_Private((u_short) portnumber,&listenport);

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

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

245:    Collective on MPI_Comm

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

253:    Output Parameter:
254: .  lab - a context to use when communicating with the server

256:    Level: intermediate

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

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

277:    Environmental variables:
278: +   PETSC_VIEWER_SOCKET_PORT portnumber
279: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

287:    Concepts: Matlab^sending data
288:    Concepts: sockets^sending data

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

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

308: PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
309: {
311:   PetscInt       def = -1;
312:   char           sdef[256];
313:   PetscTruth     tflg;

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

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

341: PetscErrorCode  PetscViewerCreate_Socket(PetscViewer v)
342: {
343:   PetscViewer_Socket *vmatlab;
344:   PetscErrorCode     ierr;

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

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

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

366:   Collective on PetscViewer

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

374:     Level: advanced

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

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

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

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


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

432:      Collective on MPI_Comm

434:      Input Parameter:
435: .    comm - the MPI communicator to share the socket PetscViewer

437:      Level: intermediate

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

445:    Environmental variables:
446: +   PETSC_VIEWER_SOCKET_PORT portnumber
447: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

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

459:      Use this for communicating with an interactive Matlab session, see PETSC_VIEWER_MATLAB_() for communicating with the Matlab engine. 

461: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
462:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
463:           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor(), PETSC_VIEWER_MATLAB_()
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: }