Actual source code: send.c
petsc-3.7.7 2017-09-25
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: /*--------------------------------------------------------------*/
62: static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
63: {
64: PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
65: PetscErrorCode ierr;
68: if (vmatlab->port) {
69: #if defined(PETSC_HAVE_CLOSESOCKET)
70: closesocket(vmatlab->port);
71: #else
72: close(vmatlab->port);
73: #endif
74: if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
75: }
76: PetscFree(vmatlab);
77: return(0);
78: }
80: /*--------------------------------------------------------------*/
83: /*
84: PetscSocketOpen - handles connected to an open port where someone is waiting.
86: .seealso: PetscSocketListen(), PetscSocketEstablish()
87: */
88: PetscErrorCode PetscOpenSocket(const char hostname[],int portnum,int *t)
89: {
90: struct sockaddr_in sa;
91: struct hostent *hp;
92: int s = 0;
93: PetscErrorCode ierr;
94: PetscBool flg = PETSC_TRUE;
95: static int refcnt = 0;
98: if (!(hp=gethostbyname(hostname))) {
99: perror("SEND: error gethostbyname: ");
100: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
101: }
102: PetscMemzero(&sa,sizeof(sa));
103: PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);
105: sa.sin_family = hp->h_addrtype;
106: sa.sin_port = htons((u_short) portnum);
107: while (flg) {
108: if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
109: perror("SEND: error socket"); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
110: }
111: if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
112: #if defined(PETSC_HAVE_WSAGETLASTERROR)
113: WSAGetLastError();
114: if (ierr == WSAEADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
115: else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
116: else if (ierr == WSAEISCONN) {
117: (*PetscErrorPrintf)("SEND: socket already connected\n");
118: Sleep((unsigned) 1);
119: } else if (ierr == WSAECONNREFUSED) {
120: /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
121: Sleep((unsigned) 1);
122: } else {
123: perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
124: }
125: #else
126: if (errno == EADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
127: else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
128: else if (errno == EISCONN) {
129: (*PetscErrorPrintf)("SEND: socket already connected\n");
130: sleep((unsigned) 1);
131: } else if (errno == ECONNREFUSED) {
132: refcnt++;
133: if (refcnt > 5) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Connection refused by remote host %s port %d",hostname,portnum);
134: PetscInfo(0,"Connection refused in attaching socket, trying again\n");
135: sleep((unsigned) 1);
136: } else {
137: perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
138: }
139: #endif
140: flg = PETSC_TRUE;
141: #if defined(PETSC_HAVE_CLOSESOCKET)
142: closesocket(s);
143: #else
144: close(s);
145: #endif
146: } else flg = PETSC_FALSE;
147: }
148: *t = s;
149: return(0);
150: }
152: #define MAXHOSTNAME 100
155: /*
156: PetscSocketEstablish - starts a listener on a socket
158: .seealso: PetscSocketListen()
159: */
160: PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
161: {
162: char myname[MAXHOSTNAME+1];
163: int s;
164: PetscErrorCode ierr;
165: struct sockaddr_in sa;
166: struct hostent *hp;
169: PetscGetHostName(myname,MAXHOSTNAME);
171: PetscMemzero(&sa,sizeof(struct sockaddr_in));
173: hp = gethostbyname(myname);
174: if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");
176: sa.sin_family = hp->h_addrtype;
177: sa.sin_port = htons((u_short)portnum);
179: if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
180: #if defined(PETSC_HAVE_SO_REUSEADDR)
181: {
182: int optval = 1; /* Turn on the option */
183: setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));
184: }
185: #endif
187: while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
188: #if defined(PETSC_HAVE_WSAGETLASTERROR)
189: WSAGetLastError();
190: if (ierr != WSAEADDRINUSE) {
191: #else
192: if (errno != EADDRINUSE) {
193: #endif
194: close(s);
195: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
196: }
197: }
198: listen(s,0);
199: *ss = s;
200: return(0);
201: }
205: /*
206: PetscSocketListens - Listens at a socket created with PetscSocketEstablish()
208: .seealso: PetscSocketEstablish()
209: */
210: PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
211: {
212: struct sockaddr_in isa;
213: #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
214: size_t i;
215: #else
216: int i;
217: #endif
220: /* wait for someone to try to connect */
221: i = sizeof(struct sockaddr_in);
222: if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
223: return(0);
224: }
228: /*@C
229: PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server.
231: Collective on MPI_Comm
233: Input Parameters:
234: + comm - the MPI communicator
235: . machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
236: a connection from elsewhere
237: - port - the port to connect to, use PETSC_DEFAULT for the default
239: Output Parameter:
240: . lab - a context to use when communicating with the server
242: Level: intermediate
244: Notes:
245: Most users should employ the following commands to access the
246: MATLAB PetscViewers
247: $
248: $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
249: $ MatView(Mat matrix,PetscViewer viewer)
250: $
251: $ or
252: $
253: $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
254: $ VecView(Vec vector,PetscViewer viewer)
256: Options Database Keys:
257: For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
258: PETSC_VIEWER_SOCKET_() or if
259: NULL is passed for machine or PETSC_DEFAULT is passed for port
260: $ -viewer_socket_machine <machine>
261: $ -viewer_socket_port <port>
263: Environmental variables:
264: + PETSC_VIEWER_SOCKET_PORT portnumber
265: - PETSC_VIEWER_SOCKET_MACHINE machine name
267: Currently the only socket client available is MATLAB. See
268: src/dm/examples/tests/ex12.c and ex12.m for an example of usage.
270: Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
271: use PetscViewerBinaryRead(), PetscViewerBinaryWrite(), PetscViewerBinarWriteStringArray(), PetscViewerBinaryGetDescriptor().
273: Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
274: .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
275: for communicating with a MATLAB Engine
277: Concepts: MATLAB^sending data
278: Concepts: sockets^sending data
280: .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
281: PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
282: PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
283: PetscBinaryViewerGetDescriptor(), PetscMatlabEngineCreate()
284: @*/
285: PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
286: {
290: PetscViewerCreate(comm,lab);
291: PetscViewerSetType(*lab,PETSCVIEWERSOCKET);
292: PetscViewerSocketSetConnection(*lab,machine,port);
293: return(0);
294: }
298: static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
299: {
301: PetscInt def = -1;
302: char sdef[256];
303: PetscBool tflg;
306: /*
307: These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
308: are listed here for the GUI to display
309: */
310: PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");
311: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);
312: if (tflg) {
313: PetscOptionsStringToInt(sdef,&def);
314: } else def = PETSCSOCKETDEFAULTPORT;
315: PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);
317: PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);
318: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);
319: if (!tflg) {
320: PetscGetHostName(sdef,256);
321: }
322: PetscOptionsTail();
323: return(0);
324: }
328: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
329: {
330: PetscViewer_Socket *vmatlab;
331: PetscErrorCode ierr;
334: PetscNewLog(v,&vmatlab);
335: vmatlab->port = 0;
336: v->data = (void*)vmatlab;
337: v->ops->destroy = PetscViewerDestroy_Socket;
338: v->ops->flush = 0;
339: v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
341: /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
342: PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);
343: return(0);
344: }
348: /*@C
349: PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
350: viewer is to use
352: Logically Collective on PetscViewer
354: Input Parameters:
355: + v - viewer to connect
356: . machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
357: a connection from elsewhere
358: - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
360: Level: advanced
362: .seealso: PetscViewerSocketOpen()
363: @*/
364: PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
365: {
366: PetscErrorCode ierr;
367: PetscMPIInt rank;
368: char mach[256];
369: PetscBool tflg;
370: PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;
374: if (port <= 0) {
375: char portn[16];
376: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);
377: if (tflg) {
378: PetscInt pport;
379: PetscOptionsStringToInt(portn,&pport);
380: port = (int)pport;
381: } else port = PETSCSOCKETDEFAULTPORT;
382: }
383: if (!machine) {
384: PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);
385: if (!tflg) {
386: PetscGetHostName(mach,256);
387: }
388: } else {
389: PetscStrncpy(mach,machine,256);
390: }
392: MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
393: if (!rank) {
394: PetscStrcmp(mach,"server",&tflg);
395: if (tflg) {
396: int listenport;
397: PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);
398: PetscSocketEstablish(port,&listenport);
399: PetscSocketListen(listenport,&vmatlab->port);
400: close(listenport);
401: } else {
402: PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);
403: PetscOpenSocket(mach,port,&vmatlab->port);
404: }
405: }
406: return(0);
407: }
409: /* ---------------------------------------------------------------------*/
410: /*
411: The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
412: is attached to a communicator, in this case the attribute is a PetscViewer.
413: */
414: static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
419: /*@C
420: PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
422: Collective on MPI_Comm
424: Input Parameter:
425: . comm - the MPI communicator to share the socket PetscViewer
427: Level: intermediate
429: Options Database Keys:
430: For use with the default PETSC_VIEWER_SOCKET_WORLD or if
431: NULL is passed for machine or PETSC_DEFAULT is passed for port
432: $ -viewer_socket_machine <machine>
433: $ -viewer_socket_port <port>
435: Environmental variables:
436: + PETSC_VIEWER_SOCKET_PORT portnumber
437: - PETSC_VIEWER_SOCKET_MACHINE machine name
439: Notes:
440: Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
441: an error code. The socket PetscViewer is usually used in the form
442: $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
444: Currently the only socket client available is MATLAB. See
445: src/dm/examples/tests/ex12.c and ex12.m for an example of usage.
447: Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
449: Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a
450: .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD
451: for communicating with a MATLAB Engine
453: .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
454: PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
455: PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_()
456: @*/
457: PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
458: {
460: PetscBool flg;
461: PetscViewer viewer;
462: MPI_Comm ncomm;
465: PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
466: if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
467: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
468: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
469: }
470: MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
471: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
472: if (!flg) { /* PetscViewer not yet created */
473: PetscViewerSocketOpen(ncomm,0,0,&viewer);
474: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
475: PetscObjectRegisterDestroy((PetscObject)viewer);
476: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
477: MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
478: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
479: }
480: PetscCommDestroy(&ncomm);
481: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
482: PetscFunctionReturn(viewer);
483: }