📄 ecostestsocket.cpp
字号:
//####COPYRIGHTBEGIN####// // ----------------------------------------------------------------------------// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.//// This program is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program 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 General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// ----------------------------------------------------------------------------// //####COPYRIGHTEND####//=================================================================//// eCosTestSocket.cpp//// Socket test class////=================================================================//=================================================================//#####DESCRIPTIONBEGIN####//// Author(s): sdf// Contributors: sdf// Date: 1999-04-01// Description: This class abstracts tcp/ip sockets for use in the testing infrastructure// Usage:////####DESCRIPTIONEND#####include "eCosStd.h"#include "eCosTestSocket.h"#include "eCosTestSerial.h"#include "eCosTrace.h"enum {ERR_TIMEOUT=20000, ERR_READ_AFTER_CLOSE=20001};// Blocking read on one or other of the data sources:// Result: 0 - error occurred// 1 - data read from socket// 2 - data read from serialint CeCosTestSocket::SSRead (CeCosTestSerial &serial,CeCosTestSocket &socket,void *pBuf,unsigned int nSize,unsigned int &nRead,bool *pbStop){ int rc=0; bool bBlocking=serial.GetBlockingReads(); bool bBlockingModified=false; while(0==pbStop || !(*pbStop)){ if(!socket.Peek(nRead)){ break; } else if(nRead){ nRead=MIN(nRead,nSize); rc=socket.recv(pBuf,nRead)?1:0; break; } else { if(bBlocking){ serial.SetBlockingReads(false); bBlockingModified=true; bBlocking=false; } if(serial.Read(pBuf,nSize,nRead)){ if(nRead>0){ rc=2; break; } } else { break; } } Sleep(1); } if(bBlockingModified){ serial.SetBlockingReads(true); } return rc;}// ctors and dtorsCeCosTestSocket::CeCosTestSocket (): m_nDefaultTimeout(10*1000), m_nSock(-1), m_nClient(0){ TRACE(_T("Create socket instance %08x\n"),(unsigned int)this);}CeCosTestSocket::CeCosTestSocket (int sock /*result of previous call of Listen*/, bool *pbStop): m_nDefaultTimeout(10*1000), m_nSock(-1), m_nClient(0){ TRACE(_T("Create socket instance %08x\n"),(unsigned int)this); Accept(sock,pbStop);}CeCosTestSocket::CeCosTestSocket (String strHost,int port,Duration dTimeout): m_nDefaultTimeout(10*1000), m_nSock(-1), m_nClient(0){ TRACE(_T("Create socket instance %08x\n"),(unsigned int)this); Connect(strHost,port,dTimeout);}bool CeCosTestSocket::Accept(int sock /*result of previous call of Listen*/, bool *pbStop){ m_nSock=-1; while(0==pbStop||!*pbStop){ struct sockaddr cli_addr; #ifndef _WIN32 unsigned #endif int clilen=sizeof(struct sockaddr); m_nSock=::accept(sock, (struct sockaddr *) &cli_addr, &clilen); SaveError(); if(-1==m_nSock){ if(WOULDBLOCK==SocketError()){ Sleep(100); continue; } } else { memcpy(&m_nClient,cli_addr.sa_data+2,4); TRACE(_T("Connection accepted from %s - socket %d\n"),(LPCTSTR )ClientName(m_nClient),m_nSock); SetSocketOptions(); break; } } return -1!=m_nSock;}int CeCosTestSocket::Listen(int nTcpPort){ // Create socket int sock=::socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { ERROR(_T("Couldn't create socket\n")); } else { TRACE(_T("Created socket %d listening on port %d\n"),sock,nTcpPort); // Bind socket to address struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof serv_addr); serv_addr.sin_family = AF_INET; serv_addr.sin_port=htons((short)nTcpPort); serv_addr.sin_addr.s_addr = INADDR_ANY; if (::bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { TRACE(_T("Couldn't bind socket on port %d\n"),nTcpPort); CloseSocket(sock); } else if (-1==::listen(sock, SOMAXCONN)){ CloseSocket(sock); TRACE(_T("socket error on listen - port %d\n"),nTcpPort); } else { #ifdef _WIN32 int nTrue=1; bool rc=(0==::ioctlsocket(sock, FIONBIO, (unsigned long *)&nTrue)); #else //UNIX int flags=::fcntl(sock,F_GETFL); flags|=O_NONBLOCK; bool rc=(0==::fcntl (sock, F_SETFL, flags)); #endif if(!rc){ TRACE(_T("Failed to set socket options on socket %d\n"),sock); } } } return sock;}bool CeCosTestSocket::Connect(String strHost,int port,Duration dTimeout){ dTimeout=TimeoutDuration(dTimeout); struct sockaddr_in serv_addr; struct hostent* host_dat; char ip[16]; // for nnn.nnn.nnn.nnn VTRACE(_T("Connect: %s:%d timeout=%d\n"),(LPCTSTR )strHost,port,dTimeout); // Get the target host address String strErr; char *pszHost=strHost.GetCString(); if (0==(host_dat=::gethostbyname(pszHost))){ SaveError(); TRACE(_T("Could not get IP address for host %s - %s\n"),(LPCTSTR )strHost,(LPCTSTR )SocketErrString()); } else { char *c=inet_ntoa( *( (struct in_addr *)host_dat->h_addr_list[0] ) ); if(0==c){ SaveError(); TRACE(_T("Could inet_ntoa %s - %s\n"),(LPCTSTR )strHost,(LPCTSTR )SocketErrString()); } else { strcpy(ip, c); memset(&serv_addr, 0, sizeof serv_addr); // Create socket m_nSock = ::socket(AF_INET, SOCK_STREAM, 0); if (-1 == m_nSock) { TRACE(_T("Could not create socket [%s:%d]\n"),(LPCTSTR )strHost,port); } else { #ifdef _WIN32 SetSocketOptions(); #endif TRACE(_T("Created socket %d connected to %s:%d\n"),m_nSock,(LPCTSTR )strHost,port); // Bind socket to address serv_addr.sin_family = AF_INET; serv_addr.sin_port=htons((short)port); SaveError(); serv_addr.sin_addr.s_addr = inet_addr(ip); // Connect to server VTRACE(_T("Connect() : connecting to server\n")); int cc=::connect(m_nSock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); SaveError(); String strMsg; if(-1==cc){ if( #ifdef _WIN32 WOULDBLOCK==SocketError() #else // UNIX EINPROGRESS==SocketError() #endif ){ // Allow dTimeout milliseconds for connect to complete fd_set set; FD_ZERO(&set); #ifdef _WIN32 #pragma warning( push ) #pragma warning( disable : 4127 ) // conditional expression is constant #endif FD_SET((unsigned)m_nSock, &set); #ifdef _WIN32 #pragma warning( pop ) #endif struct timeval tv; tv.tv_sec = dTimeout/1000; tv.tv_usec = 1000*(dTimeout % 1000); switch(::select(m_nSock, NULL, &set , NULL, &tv)){ case 0: m_nErr=ERR_TIMEOUT; strMsg.Format(_T("attempt timed out after %d seconds"),dTimeout/1000); break; case -1: SaveError(); strMsg=SocketErrString(); break; default: cc=0; } } else { strMsg=SocketErrString(); } } if(-1==cc){ TRACE(_T("Could not connect to %s:%d - %s\n"),(LPCTSTR )strHost,port,(LPCTSTR )strMsg); CloseSocket(m_nSock); } else { #ifndef _WIN32 SetSocketOptions(); #endif } } } } delete [] pszHost; return -1!=m_nSock;}bool CeCosTestSocket::sendrecv(bool bSend,const void *pData,unsigned int nLength, LPCTSTR pszMsg,Duration dTimeout,CeCosTestSocket::StopFunc pFnStop,void *pParam){ dTimeout=TimeoutDuration(dTimeout); LPCTSTR pszSR=(bSend?_T("sending"):_T("receiving")); LPTSTR c=(LPTSTR )pData; Time ft0=Now(); int nTodo=nLength; while((nTodo>0) && ((0==pFnStop) || (!pFnStop(pParam)))){ int s=bSend?::send(m_nSock, (const char *)c, nTodo, 0): ::recv(m_nSock, (char *)c, nTodo, 0); if(0==s && !bSend){ m_nErr=ERR_READ_AFTER_CLOSE; } else { SaveError(); } if(-1==s && WOULDBLOCK==SocketError()){ Duration d=Duration(Now()-ft0); if(d>dTimeout){ TRACE(_T("%d/%d mSec timeout on socket %d %s %s - processed %d/%d bytes\n") , d,dTimeout,m_nSock,pszSR,pszMsg, nLength-nTodo,nLength); m_nErr=ERR_TIMEOUT; break; } Sleep(100); } else if (s>0) { c+=s; nTodo-=s; ft0=Now(); } else { TRACE(_T("Error on socket %d %s %s - %s\n") ,m_nSock, pszSR, pszMsg, (LPCTSTR )SocketErrString()); break; } } return 0==nTodo;}// Graceful socket closedownCeCosTestSocket::~CeCosTestSocket(){ Close(); TRACE(_T("Delete socket instance %08x\n"),(unsigned int)this);}bool CeCosTestSocket::CloseSocket(int &sock){ bool rc=false; if(-1!=sock){ TRACE(_T("Closing socket %d\n"),sock); try{ shutdown(sock,0);// SD_BOTH #ifdef _WIN32 rc=(0==closesocket(sock)); #else // UNIX rc=(0==close(sock)); #endif } catch(...) { TRACE(_T("!!! Exception caught in CeCosTestSocket::CloseSocket!!!\n")); } sock=-1; } return rc;}bool CeCosTestSocket::SetSocketOptions(){ bool rc; #ifdef _WIN32 int nTrue=1; rc=(0==::ioctlsocket(m_nSock, FIONBIO, (unsigned long *)&nTrue)); SaveError(); #else // UNIX int flags=::fcntl(m_nSock,F_GETFL); SaveError(); flags|=O_NONBLOCK; rc=(0==::fcntl (m_nSock, F_SETFL, flags)); SaveError(); #endif //LINGER linger; //setsockopt(m_nSock,SOL_SOCKET,SO_LINGER,(LPCTSTR )linger, sizeof(LINGER)); if(!rc){ TRACE(_T("Failed to set socket options socket %d - %s\n"),m_nSock,(LPCTSTR )SocketErrString()); } return rc;}String CeCosTestSocket::SocketErrString(int nErr){ String str; #ifdef _WIN32 switch(nErr){ case ERR_TIMEOUT: str=_T("Read operation timed out");break; case ERR_READ_AFTER_CLOSE: str=_T("Read operation after socket closed");break; case WSAEACCES: str=_T("Permission denied");break; case WSAEADDRINUSE: str=_T("Address already in use");break; case WSAEADDRNOTAVAIL: str=_T("Cannot assign requested address");break; case WSAEAFNOSUPPORT: str=_T("Address family not supported by protocol family");break; case WSAEALREADY: str=_T("Operation already in progress");break; case WSAECONNABORTED: str=_T("Software caused connection abort");break; case WSAECONNREFUSED: str=_T("Connection refused");break; case WSAECONNRESET: str=_T("Connection reset by peer");break; case WSAEDESTADDRREQ: str=_T("Destination address required");break; case WSAEFAULT: str=_T("Bad address");break; case WSAEHOSTDOWN: str=_T("Host is down");break; case WSAEHOSTUNREACH: str=_T("No route to host");break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -