socket.cpp
来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C++ 代码 · 共 558 行 · 第 1/2 页
CPP
558 行
// -*- Mode : c++ -*-//// SUMMARY : // USAGE : // ORG : // AUTHOR : Antoine Le Hyaric -// E-MAIL : lehyaric@ann.jussieu.fr///* This file is part of Freefem++ Freefem++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Freefem++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Freefem++; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */// Communication between client and server through sockets// -------------------------------------------------------// Antoine Le Hyaric - LJLL Paris 6 - lehyaric@ann.jussieu.fr - 21/10/04// $Id: socket.cpp,v 1.12 2006-09-29 20:30:15 hecht Exp $#include <iostream>#include <cassert>#include "socket.hpp"using namespace std;// Default constructorSocket::Socket(){ socketfd=0; remotehostname=""; eof=true;}// Create a socket which opens the given TCP port to wait for calls.Socket::Socket(const Port port){ Init(); Open(port); eof=false;}// Create a socket that calls a given machineSocket::Socket(const string hostname,const Port port){ Init(); Connect(hostname,port); eof=false;}// Create a socket object from an already-open system socket// descriptor and a host name.Socket::Socket(const descriptor d,const string hostname){ socketfd=d; remotehostname=hostname; eof=false;}void Socket::IgnoreSigpipe(){#ifndef __MINGW32__ struct sigaction act; if(sigaction(SIGPIPE,(struct sigaction *)NULL,&act) < 0) throw string("Socket::ignore_sigpipe: sigaction error 1"); if(act.sa_handler == SIG_DFL){ act.sa_handler = SIG_IGN; if(sigaction(SIGPIPE,&act,(struct sigaction *)NULL) < 0) throw string("Socket::ignore_sigpipe: sigaction error 2"); }#endif}void Socket::Init(){#ifdef __MINGW32__ // (Code fragment found in WSAStartup() manual page in Microsoft // Visual C++). WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2,0); err = WSAStartup( wVersionRequested, &wsaData ); // Cannot call WSAGetLastError() since DLL is not initialized yet. if(err != 0) throw string("Socket::Init: ")+ErrorString(); // Confirm that the WinSock DLL supports 2.0. Note that if the DLL // supports versions greater than 2.0 in addition to 2.0, it will // still return 2.0 in wVersion since that is the version we // requested. if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0){ WSACleanup(); throw string("Socket::Init: Incompatible versions"); } // The WinSock DLL is acceptable. Proceed.#endif // __MINGW32__}void Socket::CleanUp(){#ifdef __MINGW32__ // Microsoft manual pages say WSAGetLastError() can be used. if(WSACleanup()==SOCKET_ERROR) throw string("Socket::CleanUp: ")+ErrorString();#endif}void Socket::Open(const Port port){ IgnoreSigpipe(); socketfd=socket(AF_INET,SOCK_STREAM,0); if(socketfd<0) throw string("Socket::open::socket: ")+ErrorString(); SockAddrIn server; server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((short)port); if(bind(socketfd,(SockAddr *)&server,sizeof(server)) < 0 || listen(socketfd,SOMAXCONN) < 0) throw string("Socket::open::bind/listen: ")+ErrorString();}Socket Socket::Listen(){ SockAddrIn net_client; descriptor d;#ifdef __MINGW32__ int len=sizeof(SockAddr); d=accept(socketfd,(SockAddr*)&net_client,&len);#else socklen_t len=sizeof(SockAddr); while((d=accept(socketfd,(SockAddr*)&net_client,&len))<0 && errno == EINTR);#endif if(d < 0) throw string("Socket::Listen: ")+ErrorString(); string hostname; HostEnt *hostptr = gethostbyaddr((char*)&(net_client.sin_addr.s_addr),4,AF_INET); if(hostptr == NULL) hostname = "unknown"; else hostname = hostptr->h_name; return Socket(d,hostname);}string Socket::getremotehostname() const{return remotehostname;}void Socket::Connect(const string hostname,const Port port){ IgnoreSigpipe(); HostEnt *hp; if(!(hp = gethostbyname(hostname.c_str())) || (socketfd = socket(AF_INET,SOCK_STREAM,0)) < 0) throw string("Socket::connect: ")+ErrorString(); SockAddrIn server; memcpy((char*)&server.sin_addr,hp->h_addr_list[0],hp->h_length); server.sin_port = htons((short)port); server.sin_family= AF_INET; int retval;#ifdef __MINGW32__ retval=connect(socketfd,(SockAddr*)&server,sizeof(server));#else while((retval = connect(socketfd,(SockAddr *)&server,sizeof(server))) < 0 && errno == EINTR);#endif if(retval < 0) throw string("Socket::Connect: ")+ErrorString();}void Socket::Close(){#ifdef __MINGW32__#define SOCKET_CLOSE(x) closesocket(x)#else#define SOCKET_CLOSE(x) close(x)#endif if(SOCKET_CLOSE(socketfd)<0) throw string("Socket::Close: ")+ErrorString(); CleanUp();}int Socket::Read(char *buf,int size){#ifdef SOCKET_DEBUG printf("Socket::Read: expecting %d bytes\n",size); // coherency checks (these are heuristic, they are only useful for // SOCKET_DEBUG) assert(size>0 && size<100000);#endif int retval;#ifdef __MINGW32__ // This must be a blocking call! Otherwise this thread takes 100% of // processing power, leaving nothing to the server thread (or we // would have to increase the priority of the server, which is not // right if we want to have a responsive client). while((retval=recv(socketfd,buf,size,0))<0 && WSAGetLastError()==WSAEWOULDBLOCK) Yield();#else while((retval = read(socketfd,buf,size))<0 && errno==EINTR);#endif // Checks that everything went fine during the read if(retval<0) throw string("Socket::Read: ")+ErrorString(); eof=retval==0; // Debug output#ifdef SOCKET_DEBUG printf("Socket::Read: \""); int i; for(i=0;i<retval;i++){#ifdef SOCKET_STRINGS printf("%c",buf[i]);#else printf("%u ",buf[i]);#endif } printf("\" length=%d\n",retval);#endif return retval;}int Socket::Write(const char *buf,int size){#ifdef SOCKET_DEBUG printf("Socket::Write: \""); int i; for(i=0;i<size;i++){#ifdef SOCKET_STRINGS printf("%c",buf[i]);#else printf("%u ",buf[i]);#endif } printf("\" length=%d\n",size);#endif int retval;#ifdef __MINGW32__ retval=send(socketfd,buf,size,0); if(retval==SOCKET_ERROR || retval!=size) throw string("Socket::Write: ")+ErrorString();#else while((retval=send(socketfd,buf,size,0))<0 && errno==EINTR); if(retval<0) throw string("Socket::Write: ")+ErrorString();#endif return retval;}// Uses unbuffered writes (for debugging)//#define UNBUFFERED_WRITESvoid Socket::bufferedwrite(const char *buf,int size){#ifdef UNBUFFERED_WRITES Write(buf,size);#else // Just stores it up until someone calls writeflush() writebuffer.append(buf,size); // Avoid sending too much data at any one time, to avoid any // indigestion in the socket. if(writebuffer.size()>200) writeflush();#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?