📄 ecossocket.cpp
字号:
//case WSAINVALIDPROVIDER: str=_T("Invalid service provider version number");break;
case WSA_IO_INCOMPLETE: str=_T("Overlapped I/O event object not in signaled state");break;
case WSA_IO_PENDING: str=_T("Overlapped operations will complete later");break;
case WSA_NOT_ENOUGH_MEMORY: str=_T("Insufficient memory available");break;
case WSANOTINITIALISED: str=_T("Successful case WSAStartup not yet:performed");break;
case WSANO_DATA: str=_T("Valid name, no data record of requested type");break;
case WSANO_RECOVERY: str=_T("This is a non-recoverable error");break;
//case WSAPROVIDERFAILEDINIT: str=_T("Unable to initialize a service provider");break;
case WSASYSCALLFAILURE: str=_T("System call failure");break;
case WSASYSNOTREADY: str=_T("Network subsystem is unavailable");break;
case WSATRY_AGAIN: str=_T("Non-authoritative host not found");break;
case WSAVERNOTSUPPORTED: str=_T("WINSOCK.DLL version out of range");break;
case WSAEDISCON: str=_T("Graceful shutdown in progress");break;
case WSA_OPERATION_ABORTED: str=_T("Overlapped operation aborted");break;
default:
str.Format(_T("Unknown error %d (0x%08x)"),nErr,nErr);
}
#else // UNIX
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;
default:
str=strerror(errno);
}
#endif
return str;
}
bool CeCosSocket::sendInteger(int n,LPCTSTR pszMsg,Duration dTimeout)
{
// This has to support cross-architectural endianness
unsigned char c[sizeof(int)];
for(unsigned int i=0;i<sizeof(int);i++){
c[i]=(unsigned char)(n&0xff);
n>>=8;
}
return send (c, sizeof(int),pszMsg,dTimeout);
}
bool CeCosSocket::recvInteger(int & n,LPCTSTR pszMsg,Duration dTimeout)
{
// This has to support cross-architectural endianness
unsigned char c[sizeof(int)];
bool rc=recv (c, sizeof(int),pszMsg,dTimeout);
n=0;
if(rc){
for(int i=sizeof(int)-1;i>=0;--i){
n<<=8;
n|=c[i];
}
}
return rc;
}
// Socket communications for strings are always non-UNICODE:
bool CeCosSocket::recvString (String &str,LPCTSTR pszMsg,Duration dTimeout)
{
int nLength;
bool rc=false;
if(recvInteger(nLength,pszMsg,dTimeout)){
if(0==nLength){
rc=true;
} else {
Buffer b(1+nLength);
char *c=(char *)b.Data();
if(c){
rc=recv(c,nLength,pszMsg,dTimeout);
c[nLength]='\0';
str=String::CStrToUnicodeStr(c);
}
}
}
return rc;
}
// Socket communications for strings are always non-UNICODE:
bool CeCosSocket::sendString (const String &str,LPCTSTR pszMsg,Duration dTimeout)
{
char *psz=str.GetCString();
int nLength=strlen(psz);
bool rc=sendInteger(nLength,pszMsg,dTimeout) && (0==nLength || send(psz,nLength,pszMsg,dTimeout));
delete [] psz;
return rc;
}
// Give indication of bytes available to be read (but don't read them)
bool CeCosSocket::Peek (unsigned int &nAvail)
{
char buf[8192];
int n=::recv(m_nSock, buf, sizeof buf, MSG_PEEK);
nAvail=0;
bool rc=false;
switch(n) {
case -1:
SaveError();
if(WOULDBLOCK==SocketError()){
rc=true; // nAvail stays==0
} else {
ERROR(_T("Peek: err=%d %s\n"),SocketError(),(LPCTSTR)SocketErrString());
}
break;
case 0:
m_nErr=ERR_READ_AFTER_CLOSE;
break;
default:
rc=true;
nAvail=n;
}
return rc;
}
// Connect tcp/ip port and serial port together.
// Traffic is passed through pFunc, passed parameter pParam.
// The pFunc function:
// may reallocate pBuf (using malloc/realloc etc...)
// must leave pBuf allocated on exit
// should not close either serial or socket
// should leave writing to its caller
// should return false if it wishes to terminate the connection (after caller has written output)
bool CeCosSocket::ConnectSocketToSerial (CeCosSocket &socket,CeCosSerial &serial,FilterFunc *pSerialToSocketFilterFunc/*=0*/,void *pSerialParam/*=0*/,FilterFunc *pSocketToSerialFilterFunc/*=0*/,void *pSocketParam/*=0*/,bool *pbStop/*=0*/)
{
serial.ClearError();
enum {BUFSIZE=8192};
void *pBuf=malloc(BUFSIZE);
TRACE(_T("ConnectSocketToSerial: connected\n"));
bool rc=true;
try {
/*
{ //hack
unsigned int nWritten;//hack
serial.Write(_T("+"),1,nWritten);//hack
}//hack
*/
while(rc && (0==pbStop || !(*pbStop))){
unsigned int nRead=0;
switch(SSRead (serial,socket,pBuf,BUFSIZE,nRead,pbStop)){
case SS_SERIAL_READ:
VTRACE(_T("Serial:%d\n"),nRead);
if(pSerialToSocketFilterFunc){
rc=pSerialToSocketFilterFunc(pBuf,nRead,serial,socket,pSerialParam);
}
if(nRead && !socket.send(pBuf,nRead)){
TRACE(_T("Failed to write to socket\n"));
rc=false;
}
break;
case SS_SOCKET_READ:
unsigned int nWritten;
VTRACE(_T("Socket:%d\n"),nRead);
if(pSocketToSerialFilterFunc){
rc=pSocketToSerialFilterFunc(pBuf,nRead,serial,socket,pSocketParam);
}
{
LPTSTR c=(LPTSTR )pBuf;
int nToWrite=nRead;
while(nToWrite>0){
if(!serial.Write(pBuf,nRead,nWritten)){
TRACE(_T("Failed to write to serial\n"));
rc=false;
break;
}
nToWrite-=nWritten;
c+=nWritten;
}
}
break;
// Error conditions:
case SS_SERIAL_ERROR:
TRACE(_T("SSRead serial error - %s\n"),(LPCTSTR)serial.ErrString());
rc=false;
break;
case SS_SOCKET_ERROR:
TRACE(_T("SSRead socket error - %s\n"),(LPCTSTR)socket.SocketErrString());
rc=false;
break;
case SS_STOPPED:
TRACE(_T("SSRead stopped\n"));
rc=false;
break;
}
}
}
catch (...){
ERROR(_T("!!! ConnectSocketToSerial exception caught!!!\n"));
free(pBuf);
throw;
}
free(pBuf);
return rc;
}
// Connect two tcp/ip ports together.
// Traffic is passed through pFunc, passed parameter pParam.
// The pFunc function:
// may reallocate pBuf (using malloc/realloc etc...)
// must leave pBuf allocated on exit
// should not close either serial or socket
// should leave writing to its caller
// should return false if it wishes to terminate the connection (after caller has written output)
bool CeCosSocket::ConnectSocketToSocket (CeCosSocket &o,FilterFunc *pSocketToSocketFilterFunc1,FilterFunc *pSocketToSocketFilterFunc2,void *pParam,bool *pbStop)
{
enum {BUFSIZE=8192};
void *pBuf=malloc(BUFSIZE);
TRACE(_T("ConnectSocketToSocket: connected\n"));
bool rc=true;
try {
while(rc && (0==pbStop || !(*pbStop))){
fd_set set;
FD_ZERO(&set);
FD_SET((unsigned)m_nSock, &set);
FD_SET((unsigned)o.m_nSock, &set);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
switch(::select(m_nSock,&set,0,0,&tv)){
case -1:
rc=false;
break;
case 1:
case 2:
{
unsigned int nAvail=0;
if(FD_ISSET((unsigned)m_nSock, &set) && Peek(nAvail) && recv(pBuf,nAvail)){
//rc=pSocketToSocketFilterFunc1(pBuf,nAvail,socket,this,o);
o.send(pBuf,nAvail);
}
if(FD_ISSET((unsigned)o.m_nSock, &set) && o.Peek(nAvail) && o.recv(pBuf,nAvail)){
//rc=pSocketToSocketFilterFunc2(pBuf,nAvail,socket,o,this);
send(pBuf,nAvail);
}
}
case 0:
break;
}
}
}
catch (...){
TRACE(_T("!!! ConnectSocketToSocket exception caught!!!\n"));
rc=false;
}
free(pBuf);
return rc;
}
bool CeCosSocket::ConnectSocketToSerial (
int nListenSock,LPCTSTR pszPort, int nBaud,
FilterFunc *pSerialToSocketFilterFunc/*=0*/,void *pSerialParam/*=0*/,FilterFunc *pSocketToSerialFilterFunc/*=0*/,void *pSocketParam/*=0*/,
bool *pbStop)
{
bool rc=false;
try{
TRACE(_T("ConnectSocketToSerial : socket %d <--> %s\n"),nListenSock,pszPort);
CeCosSerial serial;
serial.SetBlockingReads(false);
// Open serial device.
if (!serial.Open(pszPort,nBaud)){
ERROR(_T("Couldn't open port %s\n"),pszPort);
} else {
// Flush the serial buffer.
serial.Flush();
TRACE(_T("ConnectSocketToSerial: waiting for connection...\n"));
CeCosSocket socket;
if(!socket.Accept(nListenSock,pbStop)){
ERROR(_T("ConnectSocketToSerial - couldn't accept\n"));
} else {
rc=ConnectSocketToSerial (socket,serial,pSerialToSocketFilterFunc,pSerialParam,pSocketToSerialFilterFunc,pSocketParam,pbStop);
}
}
TRACE(_T("ConnectSocketToSerial : done\n"));
}
catch(...){
TRACE(_T("ConnectSocketToSerial !!!exception handled!!!\n"));
}
return rc;
}
String CeCosSocket::ClientName(int nClient)
{
char ip[4];
memcpy(ip,&nClient,4);
struct hostent *he=::gethostbyaddr((const char *)ip,4,AF_INET);
String str;
if(he){
str=String::CStrToUnicodeStr(he->h_name);
} else {
str.Format(_T("%u.%u.%u.%u"),ip[0],ip[1],ip[2],ip[3]);
}
return str;
}
String CeCosSocket::HostPort(LPCTSTR pszHost,int nPort)
{
String str;
str.Format(_T("%s:%d"),pszHost,nPort);
return str;
}
// Split the string into host:port parts. Result tells us whether it was successful.
bool CeCosSocket::ParseHostPort (LPCTSTR pszHostPort, String &strHost, int &nPort)
{
int n=_stscanf(pszHostPort,_T("%[^:]:%d"),strHost.GetBuffer(_tcslen(pszHostPort)),&nPort);
strHost.ReleaseBuffer();
return 2==n && nPort>0 && nPort<=0xffff;
}
// Is the string in the form host:port?
bool CeCosSocket::IsLegalHostPort (LPCTSTR pszHostPort)
{
int nPort=0;
String strHost;
return ParseHostPort(pszHostPort,strHost,nPort);
}
// Translate a timeout that may be one of the special values DEFAULTTIMEOUT or NOTIMEOUT to a value in milliseconds.
Duration CeCosSocket::TimeoutDuration(Duration dTimeout)
{
switch(dTimeout){
case DEFAULTTIMEOUT:
dTimeout=m_nDefaultTimeout;
break;
case NOTIMEOUT:
dTimeout=0x7fffffff;
break;
default:
break;
}
return dTimeout;
}
String CeCosSocket::SocketErrString() {
return SocketErrString(m_nErr);
}
bool CeCosSocket::SameHost(LPCTSTR host1, LPCTSTR host2)
{
return 0==_tcscmp(host1,host2) || (GetHostByName(host1)==GetHostByName(host2));
}
bool CeCosSocket::Init()
{
#ifdef _WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD( 2, 0 );
WSAStartup( wVersionRequested, &wsaData );
#endif
return true;
}
void CeCosSocket::Term()
{
#ifdef _WIN32
WSACleanup();
#endif
}
LPCTSTR CeCosSocket::MyHostName()
{
static String str;
if(str.empty()){
char szMyname[256];
if(0==gethostname(szMyname,sizeof szMyname)){
str=String::CStrToUnicodeStr(szMyname);
}
}
return str;
}
LPCTSTR CeCosSocket::MySimpleHostName()
{
static String str;
if(str.empty()){
str=MyHostName();
// Remove all after a '.'
LPCTSTR c=_tcschr(str,_TCHAR('.'));
if(c){
str.resize(c-(LPCTSTR)str);
}
}
return str;
}
const String CeCosSocket::GetHostByName(LPCTSTR pszHost)
{
typedef std::map<String,String> MapStringToString;
static MapStringToString hostmap;
MapStringToString::iterator it=hostmap.find(pszHost);
if(hostmap.end()==it){
char *h=0; // avoid erroneous gcc warning message
h=String(pszHost).GetCString();
char ip[16];
struct hostent* host_dat;
if (0!=(host_dat=::gethostbyname(h))){
char *c=inet_ntoa( *( (struct in_addr *)host_dat->h_addr_list[0] ) );
if(c){
strcpy(ip,c);
hostmap[pszHost]=String::CStrToUnicodeStr(ip);
}
}
delete [] h;
return String::CStrToUnicodeStr(ip);
} else {
return it->second;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -