Actual source code: send.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      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: #include <ctype.h>
     16: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
     17: #include <machine/endian.h>
     18: #endif
     19: #if defined(PETSC_HAVE_UNISTD_H)
     20: #include <unistd.h>
     21: #endif
     22: #if defined(PETSC_HAVE_SYS_SOCKET_H)
     23: #include <sys/socket.h>
     24: #endif
     25: #if defined(PETSC_HAVE_SYS_WAIT_H)
     26: #include <sys/wait.h>
     27: #endif
     28: #if defined(PETSC_HAVE_NETINET_IN_H)
     29: #include <netinet/in.h>
     30: #endif
     31: #if defined(PETSC_HAVE_NETDB_H)
     32: #include <netdb.h>
     33: #endif
     34: #if defined(PETSC_HAVE_FCNTL_H)
     35: #include <fcntl.h>
     36: #endif
     37: #if defined(PETSC_HAVE_IO_H)
     38: #include <io.h>
     39: #endif
     40: #if defined(PETSC_HAVE_WINSOCK2_H)
     41: #include <Winsock2.h>
     42: #endif
     43: #include <sys/stat.h>
     44: #include <../src/sys/classes/viewer/impls/socket/socket.h>

     46: #if defined(PETSC_NEED_CLOSE_PROTO)
     47: PETSC_EXTERN int close(int);
     48: #endif
     49: #if defined(PETSC_NEED_SOCKET_PROTO)
     50: PETSC_EXTERN int socket(int,int,int);
     51: #endif
     52: #if defined(PETSC_NEED_SLEEP_PROTO)
     53: PETSC_EXTERN int sleep(unsigned);
     54: #endif
     55: #if defined(PETSC_NEED_CONNECT_PROTO)
     56: PETSC_EXTERN int connect(int,struct sockaddr*,int);
     57: #endif

     59: /*--------------------------------------------------------------*/
     62: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
     63: {
     64:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
     65:   PetscErrorCode     ierr;

     68:   if (vmatlab->port) {
     69: #if defined(PETSC_HAVE_CLOSESOCKET)
     70:     closesocket(vmatlab->port);
     71: #else
     72:     close(vmatlab->port);
     73: #endif
     74:     if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
     75:   }
     76:   PetscFree(vmatlab);
     77:   return(0);
     78: }

     80: /*--------------------------------------------------------------*/
     83: /*
     84:     PetscSocketOpen - handles connected to an open port where someone is waiting.

     86: .seealso:   PetscSocketListen(), PetscSocketEstablish()
     87: */
     88: PetscErrorCode  PetscOpenSocket(const char hostname[],int portnum,int *t)
     89: {
     90:   struct sockaddr_in sa;
     91:   struct hostent     *hp;
     92:   int                s = 0;
     93:   PetscErrorCode     ierr;
     94:   PetscBool          flg = PETSC_TRUE;
     95:   static int         refcnt = 0;

     98:   if (!(hp=gethostbyname(hostname))) {
     99:     perror("SEND: error gethostbyname: ");
    100:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
    101:   }
    102:   PetscMemzero(&sa,sizeof(sa));
    103:   PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);

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

    152: #define MAXHOSTNAME 100
    155: /*
    156:    PetscSocketEstablish - starts a listener on a socket

    158: .seealso:   PetscSocketListen()
    159: */
    160: PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
    161: {
    162:   char               myname[MAXHOSTNAME+1];
    163:   int                s;
    164:   PetscErrorCode     ierr;
    165:   struct sockaddr_in sa;
    166:   struct hostent     *hp;

    169:   PetscGetHostName(myname,MAXHOSTNAME);

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

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

    176:   sa.sin_family = hp->h_addrtype;
    177:   sa.sin_port   = htons((u_short)portnum);

    179:   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
    180: #if defined(PETSC_HAVE_SO_REUSEADDR)
    181:   {
    182:     int optval = 1; /* Turn on the option */
    183:     setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));
    184:   }
    185: #endif

    187:   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
    188: #if defined(PETSC_HAVE_WSAGETLASTERROR)
    189:     WSAGetLastError();
    190:     if (ierr != WSAEADDRINUSE) {
    191: #else
    192:     if (errno != EADDRINUSE) {
    193: #endif
    194:       close(s);
    195:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
    196:     }
    197:   }
    198:   listen(s,0);
    199:   *ss = s;
    200:   return(0);
    201: }

    205: /*
    206:    PetscSocketListens - Listens at a socket created with PetscSocketEstablish()

    208: .seealso:   PetscSocketEstablish()
    209: */
    210: PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
    211: {
    212:   struct sockaddr_in isa;
    213: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
    214:   size_t             i;
    215: #else
    216:   int                i;
    217: #endif

    220:   /* wait for someone to try to connect */
    221:   i = sizeof(struct sockaddr_in);
    222:   if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
    223:   return(0);
    224: }

    228: /*@C
    229:    PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket
    230:         based server.

    232:    Collective on MPI_Comm

    234:    Input Parameters:
    235: +  comm - the MPI communicator
    236: .  machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
    237:              a connection from elsewhere
    238: -  port - the port to connect to, use PETSC_DEFAULT for the default

    240:    Output Parameter:
    241: .  lab - a context to use when communicating with the server

    243:    Level: intermediate

    245:    Notes:
    246:    Most users should employ the following commands to access the
    247:    MATLAB PetscViewers
    248: $
    249: $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
    250: $    MatView(Mat matrix,PetscViewer viewer)
    251: $
    252: $                or
    253: $
    254: $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
    255: $    VecView(Vec vector,PetscViewer viewer)

    257:    Options Database Keys:
    258:    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
    259:    PETSC_VIEWER_SOCKET_() or if
    260:     NULL is passed for machine or PETSC_DEFAULT is passed for port
    261: $    -viewer_socket_machine <machine>
    262: $    -viewer_socket_port <port>

    264:    Environmental variables:
    265: +   PETSC_VIEWER_SOCKET_PORT portnumber
    266: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

    274:    Concepts: MATLAB^sending data
    275:    Concepts: sockets^sending data

    277: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
    278:           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
    279:           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
    280:           PetscBinaryViewerGetDescriptor()
    281: @*/
    282: PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
    283: {

    287:   PetscViewerCreate(comm,lab);
    288:   PetscViewerSetType(*lab,PETSCVIEWERSOCKET);
    289:   PetscViewerSocketSetConnection(*lab,machine,port);
    290:   return(0);
    291: }

    295: static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
    296: {
    298:   PetscInt       def = -1;
    299:   char           sdef[256];
    300:   PetscBool      tflg;

    303:   /*
    304:        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
    305:     are listed here for the GUI to display
    306:   */
    307:   PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");
    308:   PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
    309:   if (tflg) {
    310:     PetscOptionsStringToInt(sdef,&def);
    311:   } else def = PETSCSOCKETDEFAULTPORT;
    312:   PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);

    314:   PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
    315:   PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
    316:   if (!tflg) {
    317:     PetscGetHostName(sdef,256);
    318:   }
    319:   PetscOptionsTail();
    320:   return(0);
    321: }

    325: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
    326: {
    327:   PetscViewer_Socket *vmatlab;
    328:   PetscErrorCode     ierr;

    331:   PetscNewLog(v,&vmatlab);
    332:   vmatlab->port          = 0;
    333:   v->data                = (void*)vmatlab;
    334:   v->ops->destroy        = PetscViewerDestroy_Socket;
    335:   v->ops->flush          = 0;
    336:   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;

    338:   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
    339:   PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);
    340:   return(0);
    341: }

    345: /*@C
    346:       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
    347:              viewer is to use

    349:   Logically Collective on PetscViewer

    351:   Input Parameters:
    352: +   v - viewer to connect
    353: .   machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
    354:              a connection from elsewhere
    355: -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default

    357:     Level: advanced

    359: .seealso: PetscViewerSocketOpen()
    360: @*/
    361: PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
    362: {
    363:   PetscErrorCode     ierr;
    364:   PetscMPIInt        rank;
    365:   char               mach[256];
    366:   PetscBool          tflg;
    367:   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;

    371:   if (port <= 0) {
    372:     char portn[16];
    373:     PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
    374:     if (tflg) {
    375:       PetscInt pport;
    376:       PetscOptionsStringToInt(portn,&pport);
    377:       port = (int)pport;
    378:     } else port = PETSCSOCKETDEFAULTPORT;
    379:   }
    380:   if (!machine) {
    381:     PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
    382:     if (!tflg) {
    383:       PetscGetHostName(mach,256);
    384:     }
    385:   } else {
    386:     PetscStrncpy(mach,machine,256);
    387:   }

    389:   MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
    390:   if (!rank) {
    391:     PetscStrcmp(mach,"server",&tflg);
    392:     if (tflg) {
    393:       int listenport;
    394:       PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);
    395:       PetscSocketEstablish(port,&listenport);
    396:       PetscSocketListen(listenport,&vmatlab->port);
    397:       close(listenport);
    398:     } else {
    399:       PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
    400:       PetscOpenSocket(mach,port,&vmatlab->port);
    401:     }
    402:   }
    403:   return(0);
    404: }

    406: /* ---------------------------------------------------------------------*/
    407: /*
    408:     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
    409:   is attached to a communicator, in this case the attribute is a PetscViewer.
    410: */
    411: static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;

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

    419:      Collective on MPI_Comm

    421:      Input Parameter:
    422: .    comm - the MPI communicator to share the socket PetscViewer

    424:      Level: intermediate

    426:    Options Database Keys:
    427:    For use with the default PETSC_VIEWER_SOCKET_WORLD or if
    428:     NULL is passed for machine or PETSC_DEFAULT is passed for port
    429: $    -viewer_socket_machine <machine>
    430: $    -viewer_socket_port <port>

    432:    Environmental variables:
    433: +   PETSC_VIEWER_SOCKET_PORT portnumber
    434: -   PETSC_VIEWER_SOCKET_MACHINE machine name

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

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

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

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

    448: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
    449:           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
    450:           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor(), PETSC_VIEWER_MATLAB_()
    451: @*/
    452: PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
    453: {
    455:   PetscBool      flg;
    456:   PetscViewer    viewer;
    457:   MPI_Comm       ncomm;

    460:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    461:   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
    462:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
    463:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    464:   }
    465:   MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
    466:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    467:   if (!flg) { /* PetscViewer not yet created */
    468:     PetscViewerSocketOpen(ncomm,0,0,&viewer);
    469:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    470:     PetscObjectRegisterDestroy((PetscObject)viewer);
    471:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    472:     MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
    473:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    474:   }
    475:   PetscCommDestroy(&ncomm);
    476:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    477:   PetscFunctionReturn(viewer);
    478: }