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: PetscErrorCode SOCKCall_Private(char *hostname,int portnum,int *t)
92: {
93: struct sockaddr_in sa;
94: struct hostent *hp;
95: int s = 0;
96: PetscErrorCode ierr;
97: PetscTruth flg = PETSC_TRUE;
100: if (!(hp=gethostbyname(hostname))) {
101: perror("SEND: error gethostbyname: ");
102: SETERRQ1(PETSC_ERR_SYS,"system error open connection to %s",hostname);
103: }
104: PetscMemzero(&sa,sizeof(sa));
105: PetscMemcpy(&sa.sin_addr,hp->h_addr,hp->h_length);
107: sa.sin_family = hp->h_addrtype;
108: sa.sin_port = htons((u_short) portnum);
109: while (flg) {
110: if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
111: perror("SEND: error socket"); SETERRQ(PETSC_ERR_SYS,"system error");
112: }
113: if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
114: #if defined(PETSC_HAVE_WSAGETLASTERROR)
115: WSAGetLastError();
116: if (ierr == WSAEADDRINUSE) {
117: (*PetscErrorPrintf)("SEND: address is in use\n");
118: } else if (ierr == WSAEALREADY) {
119: (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
120: } else if (ierr == WSAEISCONN) {
121: (*PetscErrorPrintf)("SEND: socket already connected\n");
122: Sleep((unsigned) 1);
123: } else if (ierr == WSAECONNREFUSED) {
124: /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
125: Sleep((unsigned) 1);
126: } else {
127: perror(NULL); SETERRQ(PETSC_ERR_SYS,"system error");
128: }
129: #else
130: if (errno == EADDRINUSE) {
131: (*PetscErrorPrintf)("SEND: address is in use\n");
132: } else if (errno == EALREADY) {
133: (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
134: } else if (errno == EISCONN) {
135: (*PetscErrorPrintf)("SEND: socket already connected\n");
136: sleep((unsigned) 1);
137: } else if (errno == ECONNREFUSED) {
138: /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
139: sleep((unsigned) 1);
140: } else {
141: perror(NULL); SETERRQ(PETSC_ERR_SYS,"system error");
142: }
143: #endif
144: flg = PETSC_TRUE;
145: #if defined(PETSC_HAVE_CLOSESOCKET)
146: closesocket(s);
147: #else
148: close(s);
149: #endif
150: }
151: else flg = PETSC_FALSE;
152: }
153: *t = s;
154: return(0);
155: }
159: /*@C
160: PetscViewerSocketOpen - Opens a connection to a Matlab or other socket
161: based server.
163: Collective on MPI_Comm
165: Input Parameters:
166: + comm - the MPI communicator
167: . machine - the machine the server is running on
168: - port - the port to connect to, use PETSC_DEFAULT for the default
170: Output Parameter:
171: . lab - a context to use when communicating with the server
173: Level: intermediate
175: Notes:
176: Most users should employ the following commands to access the
177: Matlab PetscViewers
178: $
179: $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
180: $ MatView(Mat matrix,PetscViewer viewer)
181: $
182: $ or
183: $
184: $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
185: $ VecView(Vec vector,PetscViewer viewer)
187: Options Database Keys:
188: For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
189: PETSC_VIEWER_SOCKET_() or if
190: PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
191: $ -viewer_socket_machine <machine>
192: $ -viewer_socket_port <port>
194: Environmental variables:
195: + PETSC_VIEWER_SOCKET_PORT portnumber
196: - PETSC_VIEWER_SOCKET_MACHINE machine name
198: Currently the only socket client available is Matlab. See
199: src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
201: Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
202: use PetscViewerBinaryRead/Write/GetDescriptor().
204: Concepts: Matlab^sending data
205: Concepts: sockets^sending data
207: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
208: PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
209: PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
210: PetscBinaryViewerGetDescriptor()
211: @*/
212: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
213: {
217: PetscViewerCreate(comm,lab);
218: PetscViewerSetType(*lab,PETSC_VIEWER_SOCKET);
219: PetscViewerSocketSetConnection(*lab,machine,port);
220: return(0);
221: }
225: PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v)
226: {
228: PetscInt def = -1;
229: char sdef[256];
230: PetscTruth tflg;
233: /*
234: These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
235: are listed here for the GUI to display
236: */
237: PetscOptionsHead("Socket PetscViewer Options");
238: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
239: if (tflg) {
240: PetscOptionsAtoi(sdef,&def);
241: } else {
242: def = PETSCSOCKETDEFAULTPORT;
243: }
244: PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);
246: PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
247: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
248: if (!tflg) {
249: PetscGetHostName(sdef,256);
250: }
251: PetscOptionsTail();
252: return(0);
253: }
258: PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
259: {
260: PetscViewer_Socket *vmatlab;
261: PetscErrorCode ierr;
264: PetscNewLog(v,PetscViewer_Socket,&vmatlab);
265: vmatlab->port = 0;
266: v->data = (void*)vmatlab;
267: v->ops->destroy = PetscViewerDestroy_Socket;
268: v->ops->flush = 0;
269: v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
271: /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
272: PetscObjectChangeTypeName((PetscObject)v,PETSC_VIEWER_BINARY);
273: return(0);
274: }
279: /*@C
280: PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
281: viewer is to use
283: Collective on PetscViewer
285: Input Parameters:
286: + v - viewer to connect
287: . machine - host to connect to
288: - port - the port on the machine one is connecting to
290: Level: advanced
292: .seealso: PetscViewerSocketOpen()
293: @*/
294: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],PetscInt port)
295: {
296: PetscErrorCode ierr;
297: PetscMPIInt rank;
298: char mach[256];
299: PetscTruth tflg;
300: PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)v->data;
303: if (port <= 0) {
304: char portn[16];
305: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
306: if (tflg) {
307: PetscOptionsAtoi(portn,&port);
308: } else {
309: port = PETSCSOCKETDEFAULTPORT;
310: }
311: }
312: if (!machine) {
313: PetscOptionsGetenv(((PetscObject)v)->comm,"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
314: if (!tflg) {
315: PetscGetHostName(mach,256);
316: }
317: } else {
318: PetscStrncpy(mach,machine,256);
319: }
321: MPI_Comm_rank(((PetscObject)v)->comm,&rank);
322: if (!rank) {
323: PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
324: SOCKCall_Private(mach,(int)port,&vmatlab->port);
325: }
326: return(0);
327: }
329: /* ---------------------------------------------------------------------*/
330: /*
331: The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
332: is attached to a communicator, in this case the attribute is a PetscViewer.
333: */
334: static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
339: /*@C
340: PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
342: Collective on MPI_Comm
344: Input Parameter:
345: . comm - the MPI communicator to share the socket PetscViewer
347: Level: intermediate
349: Options Database Keys:
350: For use with the default Matlab PetscViewer, PETSC_VIEWER_SOCKET_WORLD or if
351: PETSC_NULL is passed for machine or PETSC_DEFAULT is passed for port
352: $ -viewer_socket_machine <machine>
353: $ -viewer_socket_port <port>
355: Environmental variables:
356: + PETSC_VIEWER_SOCKET_PORT portnumber
357: - PETSC_VIEWER_SOCKET_MACHINE machine name
359: Notes:
360: Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
361: an error code. The socket PetscViewer is usually used in the form
362: $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
364: Currently the only socket client available is Matlab. See
365: src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
367: Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
369: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
370: PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
371: PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor()
372: @*/
373: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
374: {
376: PetscTruth flg;
377: PetscViewer viewer;
380: if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
381: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
382: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
383: }
384: MPI_Attr_get(comm,Petsc_Viewer_Socket_keyval,(void **)&viewer,(int*)&flg);
385: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
386: if (!flg) { /* PetscViewer not yet created */
387: PetscViewerSocketOpen(comm,0,0,&viewer);
388: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
389: PetscObjectRegisterDestroy((PetscObject)viewer);
390: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
391: MPI_Attr_put(comm,Petsc_Viewer_Socket_keyval,(void*)viewer);
392: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,__SDIR__,1,1," ");return(0);}
393: }
394: PetscFunctionReturn(viewer);
395: }