Actual source code: send.c
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;
65: if (vmatlab->port) {
66: #if defined(PETSC_HAVE_CLOSESOCKET)
67: closesocket(vmatlab->port);
68: #else
69: close(vmatlab->port);
70: #endif
72: }
73: PetscFree(vmatlab);
74: return 0;
75: }
77: /*--------------------------------------------------------------*/
78: /*@C
79: PetscSocketOpen - handles connected to an open port where someone is waiting.
81: Input Parameters:
82: + url - for example www.mcs.anl.gov
83: - portnum - for example 80
85: Output Parameter:
86: . t - the socket number
88: Notes:
89: 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: PetscBool flg = PETSC_TRUE;
103: static int refcnt = 0;
105: if (!(hp=gethostbyname(hostname))) {
106: perror("SEND: error gethostbyname: ");
107: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
108: }
109: PetscMemzero(&sa,sizeof(sa));
110: PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],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_COMM_SELF,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) (*PetscErrorPrintf)("SEND: address is in use\n");
122: else if (ierr == WSAEALREADY) (*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_COMM_SELF,PETSC_ERR_SYS,"system error");
131: }
132: #else
133: if (errno == EADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
134: else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
135: else if (errno == EISCONN) {
136: (*PetscErrorPrintf)("SEND: socket already connected\n");
137: sleep((unsigned) 1);
138: } else if (errno == ECONNREFUSED) {
139: refcnt++;
141: PetscInfo(NULL,"Connection refused in attaching socket, trying again\n");
142: sleep((unsigned) 1);
143: } else {
144: perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
145: }
146: #endif
147: flg = PETSC_TRUE;
148: #if defined(PETSC_HAVE_CLOSESOCKET)
149: closesocket(s);
150: #else
151: close(s);
152: #endif
153: } else flg = PETSC_FALSE;
154: }
155: *t = s;
156: return 0;
157: }
159: /*@C
160: PetscSocketEstablish - starts a listener on a socket
162: Input Parameters:
163: . portnumber - the port to wait at
165: Output Parameters:
166: . ss - the socket to be used with PetscSocketListen()
168: Level: advanced
170: .seealso: PetscSocketListen(), PetscOpenSocket()
172: @*/
173: PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
174: {
175: static size_t MAXHOSTNAME = 100;
176: char myname[MAXHOSTNAME+1];
177: int s;
178: struct sockaddr_in sa;
179: struct hostent *hp;
181: PetscGetHostName(myname,sizeof(myname));
183: PetscMemzero(&sa,sizeof(struct sockaddr_in));
185: hp = gethostbyname(myname);
188: sa.sin_family = hp->h_addrtype;
189: sa.sin_port = htons((u_short)portnum);
192: #if defined(PETSC_HAVE_SO_REUSEADDR)
193: {
194: int optval = 1; /* Turn on the option */
195: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));
196: }
197: #endif
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_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
208: }
209: }
210: listen(s,0);
211: *ss = s;
212: return(0);
213: }
215: /*@C
216: PetscSocketListen - Listens at a socket created with PetscSocketEstablish()
218: Input Parameter:
219: . listenport - obtained with PetscSocketEstablish()
221: Output Parameter:
222: . t - pass this to read() to read what is passed to this connection
224: Level: advanced
226: .seealso: PetscSocketEstablish()
227: @*/
228: PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
229: {
230: struct sockaddr_in isa;
231: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
232: size_t i;
233: #else
234: int i;
235: #endif
237: /* wait for someone to try to connect */
238: i = sizeof(struct sockaddr_in);
240: return 0;
241: }
243: /*@C
244: PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server.
246: Collective
248: Input Parameters:
249: + comm - the MPI communicator
250: . machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
251: a connection from elsewhere
252: - port - the port to connect to, use PETSC_DEFAULT for the default
254: Output Parameter:
255: . lab - a context to use when communicating with the server
257: Level: intermediate
259: Notes:
260: Most users should employ the following commands to access the
261: MATLAB PetscViewers
262: $
263: $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
264: $ MatView(Mat matrix,PetscViewer viewer)
265: $
266: $ or
267: $
268: $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
269: $ VecView(Vec vector,PetscViewer viewer)
271: Options Database Keys:
272: For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
273: PETSC_VIEWER_SOCKET_() or if
274: NULL is passed for machine or PETSC_DEFAULT is passed for port
275: $ -viewer_socket_machine <machine>
276: $ -viewer_socket_port <port>
278: Environmental variables:
279: + PETSC_VIEWER_SOCKET_PORT - portnumber
280: - PETSC_VIEWER_SOCKET_MACHINE - machine name
282: Currently the only socket client available is MATLAB. See
283: src/dm/tests/ex12.c and ex12.m for an example of usage.
285: Notes:
286: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
287: use PetscViewerBinaryRead(), PetscViewerBinaryWrite(), PetscViewerBinarWriteStringArray(), PetscViewerBinaryGetDescriptor().
289: Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
290: .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
291: for communicating with a MATLAB Engine
293: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
294: PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
295: PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
296: PetscBinaryViewerGetDescriptor(), PetscMatlabEngineCreate()
297: @*/
298: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
299: {
300: PetscViewerCreate(comm,lab);
301: PetscViewerSetType(*lab,PETSCVIEWERSOCKET);
302: PetscViewerSocketSetConnection(*lab,machine,port);
303: return 0;
304: }
306: static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
307: {
308: PetscInt def = -1;
309: char sdef[256];
310: PetscBool tflg;
312: /*
313: These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
314: are listed here for the GUI to display
315: */
316: PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");
317: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
318: if (tflg) {
319: PetscOptionsStringToInt(sdef,&def);
320: } else def = PETSCSOCKETDEFAULTPORT;
321: PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,NULL,NULL);
323: PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,NULL,sizeof(sdef),NULL);
324: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,sizeof(sdef),&tflg);
325: if (!tflg) {
326: PetscGetHostName(sdef,sizeof(sdef));
327: }
328: PetscOptionsTail();
329: return 0;
330: }
332: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer,PetscBool *skip)
333: {
334: PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data;
336: *skip = vsocket->skipheader;
337: return 0;
338: }
340: static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer,PetscBool skip)
341: {
342: PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data;
344: vsocket->skipheader = skip;
345: return 0;
346: }
348: static PetscErrorCode PetscViewerBinaryGetFlowControl_Socket(PetscViewer viewer,PetscInt *fc)
349: {
350: *fc = 0;
351: return 0;
352: }
354: /*MC
355: PETSCVIEWERSOCKET - A viewer that writes to a Unix socket
357: .seealso: PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
358: PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW,
359: PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
360: PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
362: Level: beginner
363: M*/
365: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
366: {
367: PetscViewer_Socket *vmatlab;
369: PetscNewLog(v,&vmatlab);
370: vmatlab->port = 0;
371: v->data = (void*)vmatlab;
372: v->ops->destroy = PetscViewerDestroy_Socket;
373: v->ops->flush = NULL;
374: v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
376: /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
377: PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);
378: PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Socket);
379: PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Socket);
380: PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Socket);
382: return 0;
383: }
385: /*@C
386: PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
387: viewer is to use
389: Logically Collective on PetscViewer
391: Input Parameters:
392: + v - viewer to connect
393: . machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
394: a connection from elsewhere
395: - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
397: Level: advanced
399: .seealso: PetscViewerSocketOpen()
400: @*/
401: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
402: {
403: PetscMPIInt rank;
404: char mach[256];
405: PetscBool tflg;
406: PetscViewer_Socket *vmatlab;
410: vmatlab = (PetscViewer_Socket*)v->data;
412: if (port <= 0) {
413: char portn[16];
414: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
415: if (tflg) {
416: PetscInt pport;
417: PetscOptionsStringToInt(portn,&pport);
418: port = (int)pport;
419: } else port = PETSCSOCKETDEFAULTPORT;
420: }
421: if (!machine) {
422: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,sizeof(mach),&tflg);
423: if (!tflg) {
424: PetscGetHostName(mach,sizeof(mach));
425: }
426: } else {
427: PetscStrncpy(mach,machine,sizeof(mach));
428: }
430: MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
431: if (rank == 0) {
432: PetscStrcmp(mach,"server",&tflg);
433: if (tflg) {
434: int listenport;
435: PetscInfo(v,"Waiting for connection from socket process on port %d\n",port);
436: PetscSocketEstablish(port,&listenport);
437: PetscSocketListen(listenport,&vmatlab->port);
438: close(listenport);
439: } else {
440: PetscInfo(v,"Connecting to socket process on port %d machine %s\n",port,mach);
441: PetscOpenSocket(mach,port,&vmatlab->port);
442: }
443: }
444: return 0;
445: }
447: /* ---------------------------------------------------------------------*/
448: /*
449: The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
450: is attached to a communicator, in this case the attribute is a PetscViewer.
451: */
452: PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
454: /*@C
455: PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
457: Collective
459: Input Parameter:
460: . comm - the MPI communicator to share the socket PetscViewer
462: Level: intermediate
464: Options Database Keys:
465: For use with the default PETSC_VIEWER_SOCKET_WORLD or if
466: NULL is passed for machine or PETSC_DEFAULT is passed for port
467: $ -viewer_socket_machine <machine>
468: $ -viewer_socket_port <port>
470: Environmental variables:
471: + PETSC_VIEWER_SOCKET_PORT - portnumber
472: - PETSC_VIEWER_SOCKET_MACHINE - machine name
474: Notes:
475: Unlike almost all other PETSc routines, Petsc_VIEWER_SOCKET_ does not return
476: an error code, it returns NULL if it fails. The socket PetscViewer is usually used in the form
477: $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
479: Currently the only socket client available is MATLAB. See
480: src/dm/tests/ex12.c and ex12.m for an example of usage.
482: Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
484: Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
485: .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
486: for communicating with a MATLAB Engine
488: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
489: PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
490: PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_()
491: @*/
492: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
493: {
495: PetscBool flg;
496: PetscViewer viewer;
497: MPI_Comm ncomm;
499: PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
500: if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
501: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,NULL);
502: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
503: }
504: MPI_Comm_get_attr(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
505: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
506: if (!flg) { /* PetscViewer not yet created */
507: PetscViewerSocketOpen(ncomm,NULL,0,&viewer);
508: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
509: PetscObjectRegisterDestroy((PetscObject)viewer);
510: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
511: MPI_Comm_set_attr(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
512: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
513: }
514: PetscCommDestroy(&ncomm);
515: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
516: return viewer;
517: }