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: }