Actual source code: send.c
petsc-3.8.4 2018-03-24
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: /*--------------------------------------------------------------*/
60: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
61: {
62: PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
63: PetscErrorCode ierr;
66: if (vmatlab->port) {
67: #if defined(PETSC_HAVE_CLOSESOCKET)
68: closesocket(vmatlab->port);
69: #else
70: close(vmatlab->port);
71: #endif
72: if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
73: }
74: PetscFree(vmatlab);
75: return(0);
76: }
78: /*--------------------------------------------------------------*/
79: /*@C
80: PetscSocketOpen - handles connected to an open port where someone is waiting.
82: Input Parameters:
83: + url - for example www.mcs.anl.gov
84: - portnum - for example 80
86: Output Paramater:
87: . t - the socket number
89: Notes: Use close() to close the socket connection
91: Use read() or PetscHTTPRequest() to read from the socket
93: Level: advanced
95: .seealso: PetscSocketListen(), PetscSocketEstablish(), PetscHTTPRequest(), PetscHTTPSConnect()
96: @*/
97: PetscErrorCode PetscOpenSocket(const char hostname[],int portnum,int *t)
98: {
99: struct sockaddr_in sa;
100: struct hostent *hp;
101: int s = 0;
102: PetscErrorCode ierr;
103: PetscBool flg = PETSC_TRUE;
104: static int refcnt = 0;
107: if (!(hp=gethostbyname(hostname))) {
108: perror("SEND: error gethostbyname: ");
109: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
110: }
111: PetscMemzero(&sa,sizeof(sa));
112: PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);
114: sa.sin_family = hp->h_addrtype;
115: sa.sin_port = htons((u_short) portnum);
116: while (flg) {
117: if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
118: perror("SEND: error socket"); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
119: }
120: if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
121: #if defined(PETSC_HAVE_WSAGETLASTERROR)
122: WSAGetLastError();
123: if (ierr == WSAEADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
124: else if (ierr == WSAEALREADY) (*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_COMM_SELF,PETSC_ERR_SYS,"system error");
133: }
134: #else
135: if (errno == EADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
136: else if (errno == EALREADY) (*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: refcnt++;
142: if (refcnt > 5) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Connection refused by remote host %s port %d",hostname,portnum);
143: PetscInfo(0,"Connection refused in attaching socket, trying again\n");
144: sleep((unsigned) 1);
145: } else {
146: perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
147: }
148: #endif
149: flg = PETSC_TRUE;
150: #if defined(PETSC_HAVE_CLOSESOCKET)
151: closesocket(s);
152: #else
153: close(s);
154: #endif
155: } else flg = PETSC_FALSE;
156: }
157: *t = s;
158: return(0);
159: }
161: #define MAXHOSTNAME 100
162: /*@C
163: PetscSocketEstablish - starts a listener on a socket
165: Input Parameters:
166: . portnumber - the port to wait at
168: Output Parameters:
169: . ss - the socket to be used with PetscSocketListen()
171: Level: advanced
173: .seealso: PetscSocketListen(), PetscOpenSocket()
175: @*/
176: PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
177: {
178: char myname[MAXHOSTNAME+1];
179: int s;
180: PetscErrorCode ierr;
181: struct sockaddr_in sa;
182: struct hostent *hp;
185: PetscGetHostName(myname,MAXHOSTNAME);
187: PetscMemzero(&sa,sizeof(struct sockaddr_in));
189: hp = gethostbyname(myname);
190: if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");
192: sa.sin_family = hp->h_addrtype;
193: sa.sin_port = htons((u_short)portnum);
195: if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
196: #if defined(PETSC_HAVE_SO_REUSEADDR)
197: {
198: int optval = 1; /* Turn on the option */
199: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));
200: }
201: #endif
203: while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
204: #if defined(PETSC_HAVE_WSAGETLASTERROR)
205: WSAGetLastError();
206: if (ierr != WSAEADDRINUSE) {
207: #else
208: if (errno != EADDRINUSE) {
209: #endif
210: close(s);
211: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
212: }
213: }
214: listen(s,0);
215: *ss = s;
216: return(0);
217: }
219: /*@C
220: PetscSocketListen - Listens at a socket created with PetscSocketEstablish()
222: Input Parameter:
223: . listenport - obtained with PetscSocketEstablish()
225: Output Parameter:
226: . t - pass this to read() to read what is passed to this connection
228: Level: advanced
230: .seealso: PetscSocketEstablish()
231: @*/
232: PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
233: {
234: struct sockaddr_in isa;
235: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
236: size_t i;
237: #else
238: int i;
239: #endif
242: /* wait for someone to try to connect */
243: i = sizeof(struct sockaddr_in);
244: if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
245: return(0);
246: }
248: /*@C
249: PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server.
251: Collective on MPI_Comm
253: Input Parameters:
254: + comm - the MPI communicator
255: . machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
256: a connection from elsewhere
257: - port - the port to connect to, use PETSC_DEFAULT for the default
259: Output Parameter:
260: . lab - a context to use when communicating with the server
262: Level: intermediate
264: Notes:
265: Most users should employ the following commands to access the
266: MATLAB PetscViewers
267: $
268: $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
269: $ MatView(Mat matrix,PetscViewer viewer)
270: $
271: $ or
272: $
273: $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
274: $ VecView(Vec vector,PetscViewer viewer)
276: Options Database Keys:
277: For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
278: PETSC_VIEWER_SOCKET_() or if
279: NULL is passed for machine or PETSC_DEFAULT is passed for port
280: $ -viewer_socket_machine <machine>
281: $ -viewer_socket_port <port>
283: Environmental variables:
284: + PETSC_VIEWER_SOCKET_PORT portnumber
285: - PETSC_VIEWER_SOCKET_MACHINE machine name
287: Currently the only socket client available is MATLAB. See
288: src/dm/examples/tests/ex12.c and ex12.m for an example of usage.
290: Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
291: use PetscViewerBinaryRead(), PetscViewerBinaryWrite(), PetscViewerBinarWriteStringArray(), PetscViewerBinaryGetDescriptor().
293: Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
294: .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
295: for communicating with a MATLAB Engine
297: Concepts: MATLAB^sending data
298: Concepts: sockets^sending data
300: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
301: PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
302: PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
303: PetscBinaryViewerGetDescriptor(), PetscMatlabEngineCreate()
304: @*/
305: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
306: {
310: PetscViewerCreate(comm,lab);
311: PetscViewerSetType(*lab,PETSCVIEWERSOCKET);
312: PetscViewerSocketSetConnection(*lab,machine,port);
313: return(0);
314: }
316: static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
317: {
319: PetscInt def = -1;
320: char sdef[256];
321: PetscBool tflg;
324: /*
325: These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
326: are listed here for the GUI to display
327: */
328: PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");
329: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
330: if (tflg) {
331: PetscOptionsStringToInt(sdef,&def);
332: } else def = PETSCSOCKETDEFAULTPORT;
333: PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);
335: PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
336: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
337: if (!tflg) {
338: PetscGetHostName(sdef,256);
339: }
340: PetscOptionsTail();
341: return(0);
342: }
344: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer,PetscBool *skip)
345: {
346: PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data;
349: *skip = vsocket->skipheader;
350: return(0);
351: }
353: static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer,PetscBool skip)
354: {
355: PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data;
358: vsocket->skipheader = skip;
359: return(0);
360: }
362: static PetscErrorCode PetscViewerBinaryGetFlowControl_Socket(PetscViewer viewer,PetscInt *fc)
363: {
365: *fc = 0;
366: return(0);
367: }
369: /*MC
370: PETSCVIEWERSOCKET - A viewer that writes to a Unix socket
373: .seealso: PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
374: PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW,
375: PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
376: PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
378: Level: beginner
379: M*/
381: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
382: {
383: PetscViewer_Socket *vmatlab;
384: PetscErrorCode ierr;
387: PetscNewLog(v,&vmatlab);
388: vmatlab->port = 0;
389: v->data = (void*)vmatlab;
390: v->ops->destroy = PetscViewerDestroy_Socket;
391: v->ops->flush = 0;
392: v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
394: /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
395: PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);
396: PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Socket);
397: PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Socket);
398: PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Socket);
400: return(0);
401: }
403: /*@C
404: PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
405: viewer is to use
407: Logically Collective on PetscViewer
409: Input Parameters:
410: + v - viewer to connect
411: . machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
412: a connection from elsewhere
413: - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
415: Level: advanced
417: .seealso: PetscViewerSocketOpen()
418: @*/
419: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
420: {
421: PetscErrorCode ierr;
422: PetscMPIInt rank;
423: char mach[256];
424: PetscBool tflg;
425: PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;
429: if (port <= 0) {
430: char portn[16];
431: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
432: if (tflg) {
433: PetscInt pport;
434: PetscOptionsStringToInt(portn,&pport);
435: port = (int)pport;
436: } else port = PETSCSOCKETDEFAULTPORT;
437: }
438: if (!machine) {
439: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
440: if (!tflg) {
441: PetscGetHostName(mach,256);
442: }
443: } else {
444: PetscStrncpy(mach,machine,256);
445: }
447: MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
448: if (!rank) {
449: PetscStrcmp(mach,"server",&tflg);
450: if (tflg) {
451: int listenport;
452: PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);
453: PetscSocketEstablish(port,&listenport);
454: PetscSocketListen(listenport,&vmatlab->port);
455: close(listenport);
456: } else {
457: PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
458: PetscOpenSocket(mach,port,&vmatlab->port);
459: }
460: }
461: return(0);
462: }
464: /* ---------------------------------------------------------------------*/
465: /*
466: The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
467: is attached to a communicator, in this case the attribute is a PetscViewer.
468: */
469: PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
472: /*@C
473: PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
475: Collective on MPI_Comm
477: Input Parameter:
478: . comm - the MPI communicator to share the socket PetscViewer
480: Level: intermediate
482: Options Database Keys:
483: For use with the default PETSC_VIEWER_SOCKET_WORLD or if
484: NULL is passed for machine or PETSC_DEFAULT is passed for port
485: $ -viewer_socket_machine <machine>
486: $ -viewer_socket_port <port>
488: Environmental variables:
489: + PETSC_VIEWER_SOCKET_PORT portnumber
490: - PETSC_VIEWER_SOCKET_MACHINE machine name
492: Notes:
493: Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
494: an error code. The socket PetscViewer is usually used in the form
495: $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
497: Currently the only socket client available is MATLAB. See
498: src/dm/examples/tests/ex12.c and ex12.m for an example of usage.
500: Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
502: Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
503: .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
504: for communicating with a MATLAB Engine
506: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
507: PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
508: PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_()
509: @*/
510: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
511: {
513: PetscBool flg;
514: PetscViewer viewer;
515: MPI_Comm ncomm;
518: PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
519: if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
520: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
521: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
522: }
523: MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
524: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
525: if (!flg) { /* PetscViewer not yet created */
526: PetscViewerSocketOpen(ncomm,0,0,&viewer);
527: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
528: PetscObjectRegisterDestroy((PetscObject)viewer);
529: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
530: MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
531: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
532: }
533: PetscCommDestroy(&ncomm);
534: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
535: PetscFunctionReturn(viewer);
536: }