Actual source code: send.c
1: #define PETSC_DLL
2: #include petsc.h
3: #include petscsys.h
5: #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
6: /* Some systems have inconsistent include files that use but do not
7: ensure that the following definitions are made */
8: typedef unsigned char u_char;
9: typedef unsigned short u_short;
10: typedef unsigned short ushort;
11: typedef unsigned int u_int;
12: typedef unsigned long u_long;
13: #endif
15: #include <errno.h>
16: #if defined(PETSC_HAVE_STDLIB_H)
17: #include <stdlib.h>
18: #endif
19: #include <sys/types.h>
20: #include <ctype.h>
21: #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
22: #include <machine/endian.h>
23: #endif
24: #if defined(PETSC_HAVE_UNISTD_H)
25: #include <unistd.h>
26: #endif
27: #if defined(PETSC_HAVE_SYS_SOCKET_H)
28: #include <sys/socket.h>
29: #endif
30: #if defined(PETSC_HAVE_SYS_WAIT_H)
31: #include <sys/wait.h>
32: #endif
33: #if defined(PETSC_HAVE_NETINET_IN_H)
34: #include <netinet/in.h>
35: #endif
36: #if defined(PETSC_HAVE_NETDB_H)
37: #include <netdb.h>
38: #endif
39: #if defined(PETSC_HAVE_FCNTL_H)
40: #include <fcntl.h>
41: #endif
42: #if defined(PETSC_HAVE_IO_H)
43: #include <io.h>
44: #endif
45: #if defined(PETSC_HAVE_WINSOCK2_H)
46: #include <Winsock2.h>
47: #endif
49: #include ../src/sys/viewer/impls/socket/socket.h
50: #include "petscfix.h"
53: #if defined(PETSC_NEED_CLOSE_PROTO)
55: #endif
56: #if defined(PETSC_NEED_SOCKET_PROTO)
58: #endif
59: #if defined(PETSC_NEED_SLEEP_PROTO)
61: #endif
62: #if defined(PETSC_NEED_CONNECT_PROTO)
64: #endif
67: /*--------------------------------------------------------------*/
70: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
71: {
72: PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
73: PetscErrorCode ierr;
76: if (vmatlab->port) {
77: #if defined(PETSC_HAVE_CLOSESOCKET)
78: closesocket(vmatlab->port);
79: #else
80: close(vmatlab->port);
81: #endif
82: if (ierr) SETERRQ(PETSC_ERR_SYS,"System error closing socket");
83: }
84: PetscFree(vmatlab);
85: return(0);
86: }
88: /*--------------------------------------------------------------*/
91: /*
92: PetscSocketOpen - handles connected to an open port where someone is waiting.
94: .seealso: SOCKAnswer_Private()
95: */
96: PetscErrorCode PetscOpenSocket(char *hostname,int portnum,int *t)
97: {
98: struct sockaddr_in sa;
99: struct hostent *hp;
100: int s = 0;
101: PetscErrorCode ierr;
102: PetscTruth flg = PETSC_TRUE;
105: if (!(hp=gethostbyname(hostname))) {
106: perror("SEND: error gethostbyname: ");
107: SETERRQ1(PETSC_ERR_SYS,"system error open connection to %s",hostname);
108: }
109: PetscMemzero(&sa,sizeof(sa));
110: PetscMemcpy(&sa.sin_addr,hp->h_addr,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_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) {
122: (*PetscErrorPrintf)("SEND: address is in use\n");
123: } else if (ierr == WSAEALREADY) {
124: (*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_ERR_SYS,"system error");
133: }
134: #else
135: if (errno == EADDRINUSE) {
136: (*PetscErrorPrintf)("SEND: address is in use\n");
137: } else if (errno == EALREADY) {
138: (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
139: } else if (errno == EISCONN) {
140: (*PetscErrorPrintf)("SEND: socket already connected\n");
141: sleep((unsigned) 1);
142: } else if (errno == ECONNREFUSED) {
143: /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
144: PetscInfo(0,"Connection refused in attaching socket, trying again");
145: sleep((unsigned) 1);
146: } else {
147: perror(NULL); SETERRQ(PETSC_ERR_SYS,"system error");
148: }
149: #endif
150: flg = PETSC_TRUE;
151: #if defined(PETSC_HAVE_CLOSESOCKET)
152: closesocket(s);
153: #else
154: close(s);
155: #endif
156: }
157: else flg = PETSC_FALSE;
158: }
159: *t = s;
160: return(0);
161: }
163: #define MAXHOSTNAME 100
164: /*-----------------------------------------------------------------*/
165: /* The listenport variable is an ugly hack. If the user hits a */
166: /* control c while we are listening then we stop listening */
167: /* but do not close the listen. Therefore if we try to bind again */
168: /* and get an address in use, close the listen which was left */
169: /* hanging; the problem is if the user uses several portnumbers */
170: /* and control c we may not be able to close the correct listener. */
171: static int listenport;
174: static PetscErrorCode SOCKEstablish_Private(u_short portnum,int *ss)
175: {
176: char myname[MAXHOSTNAME+1];
177: int s;
178: PetscErrorCode ierr;
179: struct sockaddr_in sa;
180: struct hostent *hp;
181: int optval = 1; /* Turn on the option */
184: PetscGetHostName(myname,MAXHOSTNAME);
186: PetscMemzero(&sa,sizeof(struct sockaddr_in));
188: hp = gethostbyname(myname);
189: if (!hp) SETERRQ(PETSC_ERR_SYS,"Unable to get hostent information from system");
191: sa.sin_family = hp->h_addrtype;
192: sa.sin_port = htons(portnum);
194: if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
195: SETERRQ(PETSC_ERR_SYS,"Error running socket() command");
196: }
197: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
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_ERR_SYS,"Error from bind()");
208: }
209: close(listenport);
210: }
211: listen(s,0);
212: *ss = s;
213: return(0);
214: }
218: static PetscErrorCode SOCKAnswer_Private(int portnumber,int *t)
219: {
220: PetscErrorCode ierr;
221: struct sockaddr_in isa;
222: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
223: size_t i;
224: #else
225: int i;
226: #endif
229: /* open port*/
230: SOCKEstablish_Private((u_short) portnumber,&listenport);
232: /* wait for someone to try to connect */
233: i = sizeof(struct sockaddr_in);
234: if ((*t = accept(listenport,(struct sockaddr *)&isa,(socklen_t *)&i)) < 0) {
235: SETERRQ(PETSC_ERR_SYS,"error from accept()\n");
236: }
237: close(listenport);
238: return(0);
239: }
243: /*@C
244: PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
245: based server.
247: Collective on MPI_Comm
249: Input Parameters:
250: + comm - the MPI communicator
251: . machine - the machine the server is running on,, use PETSC_NULL for the local machine, use "server" to passively wait for
252: a connection from elsewhere
253: - port - the port to connect to, use PETSC_DEFAULT for the default
255: Output Parameter:
256: . lab - a context to use when communicating with the server
258: Level: intermediate
260: Notes:
261: Most users should employ the following commands to access the
262: Matlab PetscViewers
263: $
264: $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
265: $ MatView(Mat matrix,PetscViewer viewer)
266: $
267: $ or
268: $
269: $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
270: $ VecView(Vec vector,PetscViewer viewer)
272: Options Database Keys:
273: For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
274: PETSC_VIEWER_SOCKET_() or if
275: PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
276: $ -viewer_socket_machine <machine>
277: $ -viewer_socket_port <port>
279: Environmental variables:
280: + PETSC_VIEWER_SOCKET_PORT portnumber
281: - PETSC_VIEWER_SOCKET_MACHINE machine name
283: Currently the only socket client available is Matlab. See
284: src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
286: Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
287: use PetscViewerBinaryRead/Write/GetDescriptor().
289: Concepts: Matlab^sending data
290: Concepts: sockets^sending data
292: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
293: PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
294: PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
295: PetscBinaryViewerGetDescriptor()
296: @*/
297: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
298: {
302: PetscViewerCreate(comm,lab);
303: PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);
304: PetscViewerSocketSetConnection(*lab,machine,port);
305: return(0);
306: }
310: PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
311: {
313: PetscInt def = -1;
314: char sdef[256];
315: PetscTruth tflg;
318: /*
319: These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
320: are listed here for the GUI to display
321: */
322: PetscOptionsHead("Socket PetscViewer Options");
323: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
324: if (tflg) {
325: PetscOptionsAtoi(sdef,&def);
326: } else {
327: def = PETSCSOCKETDEFAULTPORT;
328: }
329: PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);
331: PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
332: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
333: if (!tflg) {
334: PetscGetHostName(sdef,256);
335: }
336: PetscOptionsTail();
337: return(0);
338: }
343: PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
344: {
345: PetscViewer_Socket *vmatlab;
346: PetscErrorCode ierr;
349: PetscNewLog(v,PetscViewer_Socket,&vmatlab);
350: vmatlab->port = 0;
351: v->data = (void*)vmatlab;
352: v->ops->destroy = PetscViewerDestroy_Socket;
353: v->ops->flush = 0;
354: v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
356: /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
357: PetscObjectChangeTypeName((PetscObject)v,PETSC_VIEWER_BINARY);
358: return(0);
359: }
364: /*@C
365: PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
366: viewer is to use
368: Collective on PetscViewer
370: Input Parameters:
371: + v - viewer to connect
372: . machine - host to connect to, use PETSC_NULL for the local machine,use "server" to passively wait for
373: a connection from elsewhere
374: - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
376: Level: advanced
378: .seealso: PetscViewerSocketOpen()
379: @*/
380: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],PetscInt port)
381: {
382: PetscErrorCode ierr;
383: PetscMPIInt rank;
384: char mach[256];
385: PetscTruth tflg;
386: PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;
389: if (port <= 0) {
390: char portn[16];
391: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
392: if (tflg) {
393: PetscOptionsAtoi(portn,&port);
394: } else {
395: port = PETSCSOCKETDEFAULTPORT;
396: }
397: }
398: if (!machine) {
399: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
400: if (!tflg) {
401: PetscGetHostName(mach,256);
402: }
403: } else {
404: PetscStrncpy(mach,machine,256);
405: }
407: MPI_Comm_rank(((PetscObject)v)->comm,&rank);
408: if (!rank) {
409: PetscStrcmp(mach,"server",&tflg);
410: if (tflg) {
411: PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);
412: SOCKAnswer_Private((int)port,&vmatlab->port);
413: } else {
414: PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
415: PetscOpenSocket(mach,(int)port,&vmatlab->port);
416: }
417: }
418: return(0);
419: }
421: /* ---------------------------------------------------------------------*/
422: /*
423: The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
424: is attached to a communicator, in this case the attribute is a PetscViewer.
425: */
426: static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
431: /*@C
432: PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
434: Collective on MPI_Comm
436: Input Parameter:
437: . comm - the MPI communicator to share the socket PetscViewer
439: Level: intermediate
441: Options Database Keys:
442: For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD or if
443: PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
444: $ -viewer_socket_machine <machine>
445: $ -viewer_socket_port <port>
447: Environmental variables:
448: + PETSC_VIEWER_SOCKET_PORT portnumber
449: - PETSC_VIEWER_SOCKET_MACHINE machine name
451: Notes:
452: Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
453: an error code. The socket PetscViewer is usually used in the form
454: $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
456: Currently the only socket client available is Matlab. See
457: src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
459: Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
461: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
462: PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
463: PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor()
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: }