From 40d1b4b8a3d5aae6c57ab372eaeab7a47949c747 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Tue, 21 Oct 2008 18:35:42 +0000 Subject: [PATCH] more work on client/server (think I found the pb with bind fails with tcp/ip) --- Fltk/GmshSocket.h | 108 +++++++++++++++++----------------------------- Fltk/Solvers.cpp | 7 ++- 2 files changed, 43 insertions(+), 72 deletions(-) diff --git a/Fltk/GmshSocket.h b/Fltk/GmshSocket.h index 549185a193..bfd22b28fa 100644 --- a/Fltk/GmshSocket.h +++ b/Fltk/GmshSocket.h @@ -110,10 +110,7 @@ class GmshSocket{ if(first){ first = false; WSADATA wsaData; - int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if(iResult != NO_ERROR){ - // Error: Couldn't initialize Windows sockets... - } + WSAStartup(MAKEWORD(2, 2), &wsaData); } #endif } @@ -186,26 +183,9 @@ class GmshClient : public GmshSocket { // server before we attempt to connect to it... _Sleep(100); - int portno; - char remote[256]; if(strstr(sockname, "/") || strstr(sockname, "\\") || !strstr(sockname, ":")){ - // UNIX socket (testing ":" is not enough with Windows paths) - portno = -1; - } - else{ - // INET socket - char *port = strstr(sockname, ":"); - portno = atoi(port + 1); - int remotelen = strlen(sockname) - strlen(port); - if(remotelen > 0) - strncpy(remote, sockname, remotelen); - remote[remotelen] = '\0'; - } - - // create socket - - if(portno < 0){ #if !defined(WIN32) || defined(__CYGWIN__) + // UNIX socket (testing ":" is not enough with Windows paths) _sock = socket(PF_UNIX, SOCK_STREAM, 0); if(_sock < 0) return -1; // Error: Couldn't create socket @@ -220,18 +200,25 @@ class GmshClient : public GmshSocket { _Sleep(100); } #else - // Unix sockets are not available on Windows without Cygwin - return -1; + return -1; // Unix sockets are not available on Windows #endif } else{ + // TCP/IP socket _sock = socket(AF_INET, SOCK_STREAM, 0); if(_sock < 0) return -1; // Error: Couldn't create socket + // try to connect socket to host:port + char *port = strstr(sockname, ":"); + int portno = atoi(port + 1); + int remotelen = strlen(sockname) - strlen(port); + char remote[256]; + if(remotelen > 0) + strncpy(remote, sockname, remotelen); + remote[remotelen] = '\0'; struct hostent *server; if(!(server = gethostbyname(remote))) return -3; // Error: No such host - // try to connect socket to given name struct sockaddr_in addr_in; memset((char *) &addr_in, 0, sizeof(addr_in)); addr_in.sin_family = AF_INET; @@ -312,12 +299,9 @@ class GmshServer : public GmshSocket{ GmshServer() : GmshSocket(), _portno(-1) {} ~GmshServer(){} virtual int SystemCall(const char *str) = 0; - virtual int WaitForData(int socket, int num, double waitint) = 0; + virtual int NonBlockingWait(int socket, int num, double waitint) = 0; int StartClient(const char *command, const char *sockname=0, int maxdelay=4) { - static int init = 0; - static int tmpsock = 0; - int justwait = (!command || !strlen(command)); _sockname = sockname; @@ -327,26 +311,17 @@ class GmshServer : public GmshSocket{ return 1; } + int tmpsock; if(strstr(_sockname, "/") || strstr(_sockname, "\\") || !strstr(_sockname, ":")){ // UNIX socket (testing ":" is not enough with Windows paths) _portno = -1; - } - else{ - // TCP/IP socket - const char *port = strstr(_sockname, ":"); - _portno = atoi(port + 1); - } - - if(_portno < 0){ #if !defined(WIN32) || defined(__CYGWIN__) // delete the file if it already exists unlink(_sockname); - // create a socket tmpsock = socket(PF_UNIX, SOCK_STREAM, 0); if(tmpsock < 0) return -1; // Error: Couldn't create socket - // bind the socket to its name struct sockaddr_un addr_un; memset((char *) &addr_un, 0, sizeof(addr_un)); @@ -354,7 +329,6 @@ class GmshServer : public GmshSocket{ addr_un.sun_family = AF_UNIX; if(bind(tmpsock, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0) return -2; // Error: Couldn't bind socket to name - // change permissions on the socket name in case it has to be rm'd later chmod(_sockname, 0666); #else @@ -362,30 +336,25 @@ class GmshServer : public GmshSocket{ #endif } else{ - if(init != _portno){ - // We should be able to use setsockopt to allow reusing the - // same address, but I could not make it work... hence this - // horrible hack to avoid binding the name multiple times - init = _portno; - - // create a socket - tmpsock = socket(AF_INET, SOCK_STREAM, 0); + // TCP/IP socket + const char *port = strstr(_sockname, ":"); + _portno = atoi(port + 1); + // create a socket + tmpsock = socket(AF_INET, SOCK_STREAM, 0); #if !defined(WIN32) || defined(__CYGWIN__) - if(tmpsock < 0) + if(tmpsock < 0) #else - if(tmpsock == INVALID_SOCKET) + if(tmpsock == INVALID_SOCKET) #endif - return -1; // Error: Couldn't create socket - - // bind the socket to its name - struct sockaddr_in addr_in; - memset((char *) &addr_in, 0, sizeof(addr_in)); - addr_in.sin_family = AF_INET; - addr_in.sin_addr.s_addr = INADDR_ANY; - addr_in.sin_port = htons(_portno); - if(bind(tmpsock, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0) - return -2; // Error: Couldn't bind socket to name - } + return -1; // Error: Couldn't create socket + // bind the socket to its name + struct sockaddr_in addr_in; + memset((char *) &addr_in, 0, sizeof(addr_in)); + addr_in.sin_family = AF_INET; + addr_in.sin_addr.s_addr = INADDR_ANY; + addr_in.sin_port = htons(_portno); + if(bind(tmpsock, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0) + return -2; // Error: Couldn't bind socket to name } if(!justwait) @@ -398,7 +367,7 @@ class GmshServer : public GmshSocket{ if(justwait){ // wait indefinitely until we get data - if(WaitForData(tmpsock, -1, 0.5)) + if(NonBlockingWait(tmpsock, -1, 0.5)) return -6; // not an actual error: we just stopped listening } else{ @@ -420,7 +389,7 @@ class GmshServer : public GmshSocket{ len = sizeof(from_un); _sock = accept(tmpsock, (struct sockaddr *)&from_un, &len); #else - _sock = -7; // Unix sockets not available on Windows without Cygwin + _sock = -7; // Unix sockets not available on Windows #endif } else{ @@ -430,16 +399,19 @@ class GmshServer : public GmshSocket{ } if(_sock < 0) return -5; // Error: Socket accept failed + // close temporary socket +#if !defined(WIN32) || defined(__CYGWIN__) + close(tmpsock); +#else + closesocket(tmpsock); +#endif return _sock; } int StopClient() { #if !defined(WIN32) || defined(__CYGWIN__) - if(_portno < 0){ - // UNIX socket - if(unlink(_sockname) == -1) - return -1; // Impossible to unlink the socket - } + if(_portno < 0) + unlink(_sockname); close(_sock); #else closesocket(_sock); diff --git a/Fltk/Solvers.cpp b/Fltk/Solvers.cpp index 3a6f9b4848..1469e8fb7b 100644 --- a/Fltk/Solvers.cpp +++ b/Fltk/Solvers.cpp @@ -27,7 +27,7 @@ class myGmshServer : public GmshServer{ myGmshServer() : GmshServer() {} ~myGmshServer() {} int SystemCall(const char *str){ return ::SystemCall(str); } - int WaitForData(int socket, int num, double waitint) + int NonBlockingWait(int socket, int num, double waitint) { // This routine polls the socket at least every 'waitint' seconds and // returns 0 if data is available or 1 if there was en error or if the @@ -175,7 +175,7 @@ int Solver(int num, const char *args) if(stop || (num >= 0 && SINFO[num].pid < 0)) break; - stop = server->WaitForData(sock, num, 0.1); + stop = server->NonBlockingWait(sock, num, 0.1); if(stop || (num >= 0 && SINFO[num].pid < 0)) break; @@ -278,8 +278,7 @@ int Solver(int num, const char *args) } } - if(server->StopClient() < 0) - Msg::Warning("Impossible to unlink the socket '%s'", sockname.c_str()); + server->StopClient(); if(num >= 0){ Msg::StatusBar(2, false, ""); -- GitLab