//------------------------------------------------------------------------------ // // Open() - Create a connection to a specified address on a specified port // //------------------------------------------------------------------------------ bool CActiveSocket::Open(const char *pAddr, uint16 nPort) { bool bRetVal = false; if (IsSocketValid() == false) { SetSocketError(CSimpleSocket::SocketInvalidSocket); return bRetVal; } if (pAddr == NULL) { SetSocketError(CSimpleSocket::SocketInvalidAddress); return bRetVal; } if (nPort == 0) { SetSocketError(CSimpleSocket::SocketInvalidPort); return bRetVal; } switch (m_nSocketType) { case CSimpleSocket::SocketTypeTcp : { bRetVal = ConnectTCP(pAddr, nPort); break; } case CSimpleSocket::SocketTypeUdp : { bRetVal = ConnectUDP(pAddr, nPort); break; } case CSimpleSocket::SocketTypeRaw : break; default: break; } //-------------------------------------------------------------------------- // If successful then create a local copy of the address and port //-------------------------------------------------------------------------- if (bRetVal) { socklen_t nSockLen = sizeof(struct sockaddr); memset(&m_stServerSockaddr, 0, nSockLen); getpeername(m_socket, (struct sockaddr *)&m_stServerSockaddr, &nSockLen); nSockLen = sizeof(struct sockaddr); memset(&m_stClientSockaddr, 0, nSockLen); getsockname(m_socket, (struct sockaddr *)&m_stClientSockaddr, &nSockLen); SetSocketError(SocketSuccess); } return bRetVal; }
//------------------------------------------------------------------------------ // // Send() - Send data on a valid socket // //------------------------------------------------------------------------------ int32 CPassiveSocket::Send(const uint8 *pBuf, size_t bytesToSend) { SetSocketError(SocketSuccess); m_nBytesSent = 0; switch(m_nSocketType) { case CSimpleSocket::SocketTypeUdp: { if (IsSocketValid()) { if ((bytesToSend > 0) && (pBuf != NULL)) { m_timer.Initialize(); m_timer.SetStartTime(); m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stClientSockaddr, sizeof(m_stClientSockaddr)); m_timer.SetEndTime(); if (m_nBytesSent == CSimpleSocket::SocketError) { TranslateSocketError(); } } } break; } default: CSimpleSocket::Send(pBuf, bytesToSend); break; } return m_nBytesSent; }
//------------------------------------------------------------------------------ // // Select() // //------------------------------------------------------------------------------ bool TDSocket::Select(i32 nTimeoutSec, i32 nTimeoutUSec) { bool bRetVal = false; struct timeval *pTimeout = NULL; struct timeval timeout; i32 nNumDescriptors = -1; i32 nError = 0; FD_ZERO(&m_errorFds); FD_ZERO(&m_readFds); FD_ZERO(&m_writeFds); FD_SET(m_socket, &m_errorFds); FD_SET(m_socket, &m_readFds); FD_SET(m_socket, &m_writeFds); //--------------------------------------------------------------------- // If timeout has been specified then set value, otherwise set timeout // to NULL which will block until a descriptor is ready for read/write // or an error has occurred. //--------------------------------------------------------------------- if ((nTimeoutSec >= 0) || (nTimeoutUSec >= 0)) { timeout.tv_sec = nTimeoutSec; timeout.tv_usec = nTimeoutUSec; pTimeout = &timeout; } nNumDescriptors = SELECT(m_socket + 1, &m_readFds, &m_writeFds, &m_errorFds, pTimeout); // nNumDescriptors = SELECT(m_socket+1, &m_readFds, NULL, NULL, pTimeout); //---------------------------------------------------------------------- // Handle timeout //---------------------------------------------------------------------- if (nNumDescriptors == 0) { SetSocketError(TDSocket::SocketTimedout); } //---------------------------------------------------------------------- // If a file descriptor (read/write) is set then check the // socket error (SO_ERROR) to see if there is a pending error. //---------------------------------------------------------------------- else if ((FD_ISSET(m_socket, &m_readFds)) || (FD_ISSET(m_socket, &m_writeFds))) { i32 nLen = sizeof(nError); if (GETSOCKOPT(m_socket, SOL_SOCKET, SO_ERROR, &nError, &nLen) == 0) { errno = nError; if (nError == 0) { bRetVal = true; } } TranslateSocketError(); } return bRetVal; }
bool CSocket::Connect(const char* ip,int port) { isConnected=true; socketError=SocketEnum::Success; if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)//初始化套接字DLL { SetSocketError(SocketEnum::WSAStartupError); isConnected=false; } if(isConnected) { if((csocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){ SetSocketError(); isConnected=false; } } if(isConnected){ memset(&serverAddress,0,sizeof(sockaddr_in)); serverAddress.sin_family=AF_INET; long lip=inet_addr(ip); if(lip==INADDR_NONE) { SetSocketError(SocketEnum::InvalidAddress); isConnected=false; } else{ if(port<0) { SetSocketError(SocketEnum::InvalidPort); isConnected=false; }else{ serverAddress.sin_addr.S_un.S_addr= lip; serverAddress.sin_port = htons(port); if(connect(csocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){ SetSocketError(); isConnected=false; } } } } return isConnected; }
//------------------------------------------------------------------------------ // // Send() - Send data on a valid socket via a vector of buffers. // //------------------------------------------------------------------------------ i32 TDSocket::Send(const struct iovec *sendVector, i32 nNumItems) { SetSocketError(SocketSuccess); m_nBytesSent = 0; if ((m_nBytesSent = WRITEV(m_socket, sendVector, nNumItems)) == TDSocket::SocketError) { TranslateSocketError(); } return m_nBytesSent; }
//------------------------------------------------------------------------------ // // ConnectUDP() - // //------------------------------------------------------------------------------ bool CActiveSocket::ConnectUDP(const char *pAddr, uint16 nPort) { bool bRetVal = false; struct in_addr stIpAddress; //------------------------------------------------------------------ // Pre-connection setup that must be preformed //------------------------------------------------------------------ memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); m_stServerSockaddr.sin_family = AF_INET; if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL) { #ifdef WIN32 TranslateSocketError(); #else if (h_errno == HOST_NOT_FOUND) { SetSocketError(SocketInvalidAddress); } #endif return bRetVal; } memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length); m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError) { TranslateSocketError(); return bRetVal; } m_stServerSockaddr.sin_port = htons(nPort); //------------------------------------------------------------------ // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. // //------------------------------------------------------------------ m_timer.Initialize(); m_timer.SetStartTime(); if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError) { bRetVal = true; } TranslateSocketError(); m_timer.SetEndTime(); return bRetVal; }
//------------------------------------------------------------------------------ // // Accept() - // //------------------------------------------------------------------------------ CActiveSocket *CPassiveSocket::Accept(uint32_t timeout_sec) { uint32_t nSockLen; std::auto_ptr<CActiveSocket> ClientSocket; SOCKET socket = CSimpleSocket::SocketError; if (m_nSocketType != CSimpleSocket::SocketTypeTcp) { SetSocketError(CSimpleSocket::SocketProtocolError); return 0; } ClientSocket.reset (new CActiveSocket(m_compress_, m_nSocketType)); //-------------------------------------------------------------------------- // Wait for incoming connection. //-------------------------------------------------------------------------- CSocketError socketErrno = SocketSuccess; nSockLen = sizeof(m_stClientSockaddr); do { errno = 0; if (!Select (timeout_sec, 0)) return 0; socket = accept(m_socket, (struct sockaddr *)&m_stClientSockaddr, (socklen_t *)&nSockLen); if (socket != -1) { ClientSocket->SetSocketHandle(socket); ClientSocket->TranslateSocketError(); socketErrno = ClientSocket->GetSocketError(); socklen_t nSockLen = sizeof(struct sockaddr); //------------------------------------------------------------- // Store client and server IP and port information for this // connection. //------------------------------------------------------------- getpeername(m_socket, (struct sockaddr *)&ClientSocket->m_stClientSockaddr, &nSockLen); memcpy((void *)&ClientSocket->m_stClientSockaddr, (void *)&m_stClientSockaddr, nSockLen); memset(&ClientSocket->m_stServerSockaddr, 0, nSockLen); getsockname(m_socket, (struct sockaddr *)&ClientSocket->m_stServerSockaddr, &nSockLen); } else { TranslateSocketError(); socketErrno = GetSocketError(); } } while (socketErrno == CSimpleSocket::SocketInterrupted); if (socketErrno != CSimpleSocket::SocketSuccess) return 0; return ClientSocket.release (); }
//------------------------------------------------------------------------------ // // ConnectRAW() - // //------------------------------------------------------------------------------ bool TDSocket::ConnectRAW(const char *pAddr, i16 nPort) { bool bRetVal = false; struct in_addr stIpAddress; //------------------------------------------------------------------ // Pre-connection setup that must be preformed //------------------------------------------------------------------ memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); m_stServerSockaddr.sin_family = AF_INET; hostent * pHE = NULL; if ((pHE = GETHOSTBYNAME(pAddr)) == NULL) { #ifdef WIN32 TranslateSocketError(); #else if (h_errno == HOST_NOT_FOUND) { SetSocketError(SocketInvalidAddress); } #endif return bRetVal; } memcpy(&stIpAddress, pHE->h_addr_list[0], pHE->h_length); m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; if ((i32)m_stServerSockaddr.sin_addr.s_addr == TDSocket::SocketError) { TranslateSocketError(); return bRetVal; } m_stServerSockaddr.sin_port = htons(nPort); //------------------------------------------------------------------ // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. // //------------------------------------------------------------------ if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != TDSocket::SocketError) { bRetVal = true; } TranslateSocketError(); return bRetVal; }
//------------------------------------------------------------------------------ // // Close() - Close socket and free up any memory allocated for the socket // //------------------------------------------------------------------------------ bool CPassiveSocket::Close(void) { if (IsSocketValid()) { if (shutdown(m_socket, CSimpleSocket::Both) != CSimpleSocket::SocketError) { if (CLOSE(m_socket) != CSimpleSocket::SocketError) { m_socket = CSimpleSocket::SocketError; SetSocketError(CSimpleSocket::SocketInvalidSocket); return true; } } } TranslateSocketError(); return false; }
int CSocket::Receive(int strLen) { recvCount=0; if(!IsSocketValid() || !isConnected) { return recvCount; } if(strLen<1) { return recvCount; } if(buffer!=NULL) { delete buffer; buffer=NULL; } buffer=new char[strLen]; SetSocketError(SocketEnum::Success); while(1){ cout << "wait rec" << endl; recvCount=recv(csocket,buffer,strLen,0) ; cout << "rec over" << endl; if(recvCount>0){ buffer[recvCount]='\0'; if(IsExit()) { Send(buffer,recvCount); delete buffer; buffer=NULL; recvCount=0; break; }else{ for (int i = 0; i < recvCount; i++) { cout << buffer[i] << endl; } cout<<buffer<<endl; } } } return recvCount; }
//------------------------------------------------------------------------------ // // SetWindowSize() // //------------------------------------------------------------------------------ u16 TDSocket::SetWindowSize(u32 nOptionName, u32 nWindowSize) { u32 nRetVal = 0; //------------------------------------------------------------------------- // no socket given, return system default allocate our own new socket //------------------------------------------------------------------------- if (m_socket != TDSocket::SocketError) { nRetVal = SETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nWindowSize, sizeof(nWindowSize)); TranslateSocketError(); } else { SetSocketError(TDSocket::SocketInvalidSocket); } return (u16)nWindowSize; }
//------------------------------------------------------------------------------ // // BindInterface() // //------------------------------------------------------------------------------ bool TDSocket::BindInterface(u8 *pInterface) { bool bRetVal = false; struct in_addr stInterfaceAddr; if (GetMulticast() == true) { if (pInterface) { stInterfaceAddr.s_addr = inet_addr((const char *)pInterface); if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_IF, &stInterfaceAddr, sizeof(stInterfaceAddr)) == SocketSuccess) { bRetVal = true; } } } else { SetSocketError(TDSocket::SocketProtocolError); } return bRetVal; }
//------------------------------------------------------------------------------ // // GetWindowSize() // //------------------------------------------------------------------------------ u16 TDSocket::GetWindowSize(u32 nOptionName) { u32 nTcpWinSize = 0; //------------------------------------------------------------------------- // no socket given, return system default allocate our own new socket //------------------------------------------------------------------------- if (m_socket != TDSocket::SocketError) { socklen_t nLen = sizeof(nTcpWinSize); //--------------------------------------------------------------------- // query for buffer size //--------------------------------------------------------------------- GETSOCKOPT(m_socket, SOL_SOCKET, nOptionName, &nTcpWinSize, &nLen); TranslateSocketError(); } else { SetSocketError(TDSocket::SocketInvalidSocket); } return nTcpWinSize; }
//------------------------------------------------------------------------------ // // Accept() - // //------------------------------------------------------------------------------ CActiveSocket *CPassiveSocket::Accept() { uint32 nSockLen; CActiveSocket *pClientSocket = NULL; SOCKET socket = CSimpleSocket::SocketError; if (m_nSocketType != CSimpleSocket::SocketTypeTcp) { SetSocketError(CSimpleSocket::SocketProtocolError); return pClientSocket; } pClientSocket = new CActiveSocket(); //-------------------------------------------------------------------------- // Wait for incoming connection. //-------------------------------------------------------------------------- if (pClientSocket != NULL) { CSocketError socketErrno = SocketSuccess; m_timer.Initialize(); m_timer.SetStartTime(); nSockLen = sizeof(m_stClientSockaddr); do { errno = 0; socket = accept(m_socket, (struct sockaddr *)&m_stClientSockaddr, (socklen_t *)&nSockLen); if (socket != -1) { pClientSocket->SetSocketHandle(socket); pClientSocket->TranslateSocketError(); socketErrno = pClientSocket->GetSocketError(); socklen_t nSockLen = sizeof(struct sockaddr); //------------------------------------------------------------- // Store client and server IP and port information for this // connection. //------------------------------------------------------------- getpeername(m_socket, (struct sockaddr *)&pClientSocket->m_stClientSockaddr, &nSockLen); memcpy((void *)&pClientSocket->m_stClientSockaddr, (void *)&m_stClientSockaddr, nSockLen); memset(&pClientSocket->m_stServerSockaddr, 0, nSockLen); getsockname(m_socket, (struct sockaddr *)&pClientSocket->m_stServerSockaddr, &nSockLen); } else { TranslateSocketError(); socketErrno = GetSocketError(); } } while (socketErrno == CSimpleSocket::SocketInterrupted); m_timer.SetEndTime(); if (socketErrno != CSimpleSocket::SocketSuccess) { delete pClientSocket; pClientSocket = NULL; } } return pClientSocket; }
Status::Status(sf::Socket::Status _socket_status) : Status() { SetSocketError(_socket_status); }
//------------------------------------------------------------------------------ // // TranslateSocketError() - // //------------------------------------------------------------------------------ void TDSocket::TranslateSocketError(void) { #ifndef WIN32 switch (errno) { case EXIT_SUCCESS: SetSocketError(TDSocket::SocketSuccess); break; case ENOTCONN: SetSocketError(TDSocket::SocketNotconnected); break; case ENOTSOCK: case EBADF: case EACCES: case EAFNOSUPPORT: case EMFILE: case ENFILE: case ENOBUFS: case ENOMEM: case EPROTONOSUPPORT: SetSocketError(TDSocket::SocketInvalidSocket); break; case ECONNREFUSED: SetSocketError(TDSocket::SocketConnectionRefused); break; case ETIMEDOUT: SetSocketError(TDSocket::SocketTimedout); break; case EINPROGRESS: SetSocketError(TDSocket::SocketEinprogress); break; case EWOULDBLOCK: // case EAGAIN: SetSocketError(TDSocket::SocketEwouldblock); break; case EINTR: SetSocketError(TDSocket::SocketInterrupted); break; case ECONNABORTED: SetSocketError(TDSocket::SocketConnectionAborted); break; case EINVAL: case EPROTO: SetSocketError(TDSocket::SocketProtocolError); break; case EPERM: SetSocketError(TDSocket::SocketFirewallError); break; case EFAULT: SetSocketError(TDSocket::SocketInvalidSocketBuffer); break; case ECONNRESET: SetSocketError(TDSocket::SocketConnectionReset); break; case ENOPROTOOPT: SetSocketError(TDSocket::SocketConnectionReset); break; default: SetSocketError(TDSocket::SocketEunknown); break; } #endif #ifdef WIN32 i32 nError = WSAGetLastError(); switch (nError) { case EXIT_SUCCESS: SetSocketError(TDSocket::SocketSuccess); break; case WSAEBADF: case WSAENOTCONN: SetSocketError(TDSocket::SocketNotconnected); break; case WSAEINTR: SetSocketError(TDSocket::SocketInterrupted); break; case WSAEACCES: case WSAEAFNOSUPPORT: case WSAEINVAL: case WSAEMFILE: case WSAENOBUFS: case WSAEPROTONOSUPPORT: SetSocketError(TDSocket::SocketInvalidSocket); break; case WSAECONNREFUSED: SetSocketError(TDSocket::SocketConnectionRefused); break; case WSAETIMEDOUT: SetSocketError(TDSocket::SocketTimedout); break; case WSAEINPROGRESS: SetSocketError(TDSocket::SocketEinprogress); break; case WSAECONNABORTED: SetSocketError(TDSocket::SocketConnectionAborted); break; case WSAEWOULDBLOCK: SetSocketError(TDSocket::SocketEwouldblock); break; case WSAENOTSOCK: SetSocketError(TDSocket::SocketInvalidSocket); break; case WSAECONNRESET: SetSocketError(TDSocket::SocketConnectionReset); break; case WSANO_DATA: SetSocketError(TDSocket::SocketInvalidAddress); break; case WSAEADDRINUSE: SetSocketError(TDSocket::SocketAddressInUse); break; case WSAEFAULT: SetSocketError(TDSocket::SocketInvalidPointer); break; default: SetSocketError(TDSocket::SocketEunknown); break; } #endif }
//------------------------------------------------------------------------------ // // Receive() - Attempts to receive a block of data on an established // connection. Data is received in an internal buffer managed // by the class. This buffer is only valid until the next call // to Receive(), a call to Close(), or until the object goes out // of scope. // //------------------------------------------------------------------------------ i32 TDSocket::Receive(i32 nMaxBytes) { m_nBytesReceived = 0; //-------------------------------------------------------------------------- // If the socket is invalid then return false. //-------------------------------------------------------------------------- if (IsSocketValid() == false) { return m_nBytesReceived; } //-------------------------------------------------------------------------- // Free existing buffer and allocate a new buffer the size of // nMaxBytes. //-------------------------------------------------------------------------- if (nMaxBytes != m_nBufferSize) { m_nBufferSize = nMaxBytes; m_pBuffer.clear(); m_pBuffer.resize(m_nBufferSize); } SetSocketError(SocketSuccess); switch (m_nSocketType) { //---------------------------------------------------------------------- // If zero bytes are received, then return. If SocketERROR is // received, free buffer and return CSocket::SocketError (-1) to caller. //---------------------------------------------------------------------- case TDSocket::SocketTypeTcp: { do { m_nBytesReceived = RECV(m_socket, &m_pBuffer[m_nBytesReceived], nMaxBytes - m_nBytesReceived, m_nFlags); TranslateSocketError(); } while (IsSocketValid() && (GetSocketError() == TDSocket::SocketInterrupted)); break; } case TDSocket::SocketTypeUdp: { socklen_t srcSize; srcSize = sizeof(struct sockaddr_in); if (GetMulticast() == true) { do { m_nBytesReceived = RECVFROM(m_socket, &m_pBuffer[0], nMaxBytes, 0, &m_stMulticastGroup, &srcSize); TranslateSocketError(); } while (IsSocketValid() && GetSocketError() == TDSocket::SocketInterrupted); } else { do { m_nBytesReceived = RECVFROM(m_socket, &m_pBuffer[0], nMaxBytes, 0, &m_stClientSockaddr, &srcSize); TranslateSocketError(); } while (GetSocketError() == TDSocket::SocketInterrupted); } break; } default: break; } TranslateSocketError(); return m_nBytesReceived; }
//------------------------------------------------------------------------------ // // Listen() - // //------------------------------------------------------------------------------ bool CPassiveSocket::Listen(const char *pAddr, uint16 nPort, int32 nConnectionBacklog) { bool bRetVal = false; #ifdef WIN32 ULONG inAddr; #else in_addr_t inAddr; int32 nReuse; nReuse = IPTOS_LOWDELAY; //-------------------------------------------------------------------------- // Set the following socket option SO_REUSEADDR. This will allow the file // descriptor to be reused immediately after the socket is closed instead // of setting in a TIMED_WAIT state. //-------------------------------------------------------------------------- SETSOCKOPT(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&nReuse, sizeof(int32)); SETSOCKOPT(m_socket, IPPROTO_TCP, IP_TOS, &nReuse, sizeof(int32)); #endif memset(&m_stServerSockaddr,0,sizeof(m_stServerSockaddr)); m_stServerSockaddr.sin_family = AF_INET; m_stServerSockaddr.sin_port = htons(nPort); //-------------------------------------------------------------------------- // If no IP Address (interface ethn) is supplied, or the loop back is // specified then bind to any interface, else bind to specified interface. //-------------------------------------------------------------------------- if ((pAddr == NULL) || (!strlen(pAddr))) { m_stServerSockaddr.sin_addr.s_addr = htonl(INADDR_ANY); } else { if ((inAddr = inet_addr(pAddr)) != INADDR_NONE) { m_stServerSockaddr.sin_addr.s_addr = inAddr; } } m_timer.Initialize(); m_timer.SetStartTime(); //-------------------------------------------------------------------------- // Bind to the specified port //-------------------------------------------------------------------------- if (bind(m_socket, (struct sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError) { if (m_nSocketType == CSimpleSocket::SocketTypeTcp) { if (listen(m_socket, nConnectionBacklog) != CSimpleSocket::SocketError) { bRetVal = true; } } else { bRetVal = true; } } m_timer.SetEndTime(); //-------------------------------------------------------------------------- // If there was a socket error then close the socket to clean out the // connection in the backlog. //-------------------------------------------------------------------------- TranslateSocketError(); if (bRetVal == false) { CSocketError err = GetSocketError(); Close(); SetSocketError(err); } return bRetVal; }
//------------------------------------------------------------------------------ // // Send() - Send data on a valid socket // //------------------------------------------------------------------------------ i32 TDSocket::Send(const char *pBuf, size_t bytesToSend) { SetSocketError(SocketSuccess); m_nBytesSent = 0; switch (m_nSocketType) { case TDSocket::SocketTypeTcp: { if (IsSocketValid()) { if ((bytesToSend > 0) && (pBuf != NULL)) { //--------------------------------------------------------- // Check error condition and attempt to resend if call // was interrupted by a signal. //--------------------------------------------------------- do { m_nBytesSent = SEND(m_socket, pBuf, bytesToSend, 0); TranslateSocketError(); } while (GetSocketError() == TDSocket::SocketInterrupted); } } break; } case TDSocket::SocketTypeUdp: { if (IsSocketValid()) { if ((bytesToSend > 0) && (pBuf != NULL)) { //--------------------------------------------------------- // Check error condition and attempt to resend if call // was interrupted by a signal. //--------------------------------------------------------- // if (GetMulticast()) // { // do // { // m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stMulticastGroup, // sizeof(m_stMulticastGroup)); // TranslateSocketError(); // } while (GetSocketError() == TDSocket::SocketInterrupted); // } // else { do { m_nBytesSent = SENDTO(m_socket, pBuf, bytesToSend, 0, (const sockaddr *)&m_stServerSockaddr, sizeof(m_stServerSockaddr)); TranslateSocketError(); } while (GetSocketError() == TDSocket::SocketInterrupted); } } } break; } default: break; } return m_nBytesSent; }
int UDPSocket::SetReadTimeout(int seconds, int useconds) { struct timeval tv; tv.tv_sec=seconds; tv.tv_usec=useconds; PPLSOCKET *s=(PPLSOCKET*)socket; if (!s) { SetError(275); return 0; } #ifdef WIN32 if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv,sizeof(tv))!=0) { #else if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(void*)&tv,sizeof(tv))!=0) { #endif SetError(350); return 0; } return 1; } int UDPSocket::RecvFrom(void *buffer, int maxlen) /*! \brief UDP-Packet empfangen * * \header \#include <ppl6.h> * \desc * Diese Funktion wartet auf ein UDP-Packet * * \param buffer Ein Pointer auf den Puffer, in den die Daten geschrieben werden sollen * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { struct sockaddr from; #ifdef _WIN32 int len; #else socklen_t len=0; #endif PPLSOCKET *s=(PPLSOCKET*)socket; if (!s) { socket=malloc(sizeof(PPLSOCKET)); s=(PPLSOCKET*)socket; s->sd=-1; } if (s->sd<0) s->sd=::socket(AF_INET,SOCK_DGRAM,0); #ifdef _WIN32 len=sizeof(struct sockaddr); int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,&from,&len); //int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,NULL,0); #else int ret=::recvfrom(s->sd,buffer,maxlen,0,&from,&len); #endif if (ret<0) { SetSocketError(); return -1; } return ret; } int UDPSocket::GetDescriptor() { if (!socket) return 0; PPLSOCKET *s=(PPLSOCKET*)socket; #ifdef _WIN32 return (int)s->sd; #else return s->sd; #endif } int UDPSocket::RecvFrom(void *buffer, int maxlen, CString &host, int *port) /*! \brief UDP-Packet empfangen * * \header \#include <ppl6.h> * \desc * Diese Funktion wartet auf ein UDP-Packet * * \param buffer Ein Pointer auf den Puffer, in den die Daten geschrieben werden sollen * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können * \param host Pointer auf einen String, in dem die Absender-IP des Pakets gespeichert wird * \param port Port des Absenders * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.2.3 eingeführt */ { struct sockaddr_in from; #ifdef _WIN32 int len; #else socklen_t len=0; #endif PPLSOCKET *s=(PPLSOCKET*)socket; if (!s) { socket=malloc(sizeof(PPLSOCKET)); s=(PPLSOCKET*)socket; s->sd=-1; } if (s->sd<0) s->sd=::socket(AF_INET,SOCK_DGRAM,0); #ifdef _WIN32 len=sizeof(struct sockaddr); int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,(sockaddr*)&from,&len); //int ret=::recvfrom(s->sd,(char*)buffer,maxlen,0,NULL,0); #else int ret=::recvfrom(s->sd,buffer,maxlen,0,(struct sockaddr *)&from,&len); #endif if (ret<0) { SetSocketError(); return -1; } char hostname[1024]; char servname[32]; bzero(hostname,1024); bzero(servname,32); ppl6::HexDump(&from,sizeof(struct sockaddr)); if (getnameinfo((const sockaddr*)&from,len, hostname,1023, servname,31,NI_NUMERICHOST|NI_NUMERICSERV)!=0) { host.Set(""); *port=0; } else { host.Set(hostname); *port=atoi(servname); } return ret; } int UDPSocket::Bind(const char *host, int port) { int addrlen=0; if (!socket) { socket=malloc(sizeof(PPLSOCKET)); if (!socket) { SetError(2); return 0; } PPLSOCKET *s=(PPLSOCKET*)socket; s->sd=0; s->proto=6; s->ipname=NULL; s->port=port; //s->addrlen=0; } PPLSOCKET *s=(PPLSOCKET*)socket; //if (s->sd) Disconnect(); if (s->ipname) free(s->ipname); s->ipname=NULL; struct addrinfo hints, *res, *ressave; bzero(&hints, sizeof(struct addrinfo)); hints.ai_flags=AI_PASSIVE; hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_DGRAM; int n; int on=1; #ifdef _WIN32 SOCKET listenfd; #else int listenfd; #endif // Prüfen, ob host ein Wildcard ist if (host!=NULL && strlen(host)==0) host=NULL; if (host!=NULL && host[0]=='*') host=NULL; if (host) { char portstr[10]; sprintf(portstr,"%i",port); if ((n=getaddrinfo(host,portstr,&hints,&res))!=0) { SetError(273,"%s, %s",host,gai_strerror(n)); return 0; } ressave=res; do { listenfd=::socket(res->ai_family,res->ai_socktype,res->ai_protocol); if (listenfd<0) continue; // Error, try next one if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on))!=0) { freeaddrinfo(ressave); SetError(334); return 0; } if (::bind(listenfd,res->ai_addr,res->ai_addrlen)==0) { addrlen=res->ai_addrlen; break; } shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif listenfd=0; } while ((res=res->ai_next)!=NULL); freeaddrinfo(ressave); } else { listenfd=::socket(AF_INET, SOCK_DGRAM, 0); if (listenfd>=0) { struct sockaddr_in addr; bzero(&addr,sizeof(addr)); addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); addr.sin_family = AF_INET; /* bind server port */ if(::bind(listenfd, (struct sockaddr *) &addr, sizeof(addr))!=0) { shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif SetError(266); return 0; } s->sd=listenfd; //s->addrlen=0; //connected=1; return 1; } } if (listenfd<0) { SetError(265,"Host: %s, Port: %d",host,port); return 0; } if (res==NULL) { SetError(266,"Host: %s, Port: %d",host,port); return 0; } s->sd=listenfd; //s->addrlen=addrlen; //connected=1; return 1; }
//------------------------------------------------------------------------------ // // ConnectTCP() - // //------------------------------------------------------------------------------ bool TDSocket::ConnectTCP(const char *pAddr, i16 nPort) { bool bRetVal = false; struct in_addr stIpAddress; //------------------------------------------------------------------ // Preconnection setup that must be preformed //------------------------------------------------------------------ memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr)); m_stServerSockaddr.sin_family = AF_INET; hostent * pHE = NULL; if ((pHE = GETHOSTBYNAME(pAddr)) == NULL) { #ifdef WIN32 TranslateSocketError(); #else if (h_errno == HOST_NOT_FOUND) { SetSocketError(SocketInvalidAddress); } #endif return bRetVal; } memcpy(&stIpAddress, pHE->h_addr_list[0], pHE->h_length); m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr; if ((i32)m_stServerSockaddr.sin_addr.s_addr == TDSocket::SocketError) { TranslateSocketError(); return bRetVal; } m_stServerSockaddr.sin_port = htons(nPort); //------------------------------------------------------------------ // Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only. // //------------------------------------------------------------------ if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) == TDSocket::SocketError) { //-------------------------------------------------------------- // Get error value this might be a non-blocking socket so we // must first check. //-------------------------------------------------------------- TranslateSocketError(); //-------------------------------------------------------------- // If the socket is non-blocking and the current socket error // is SocketEinprogress or SocketEwouldblock then poll connection // with select for designated timeout period. // Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK. //-------------------------------------------------------------- if ((IsNonblocking()) && ((GetSocketError() == TDSocket::SocketEwouldblock) || (GetSocketError() == TDSocket::SocketEinprogress))) { bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec()); } } else { TranslateSocketError(); bRetVal = true; } return bRetVal; }
//------------------------------------------------------------------------------ // // Receive() - Attempts to receive a block of data on an established // connection. Data is received in an internal buffer managed // by the class. This buffer is only valid until the next call // to Receive(), a call to Close(), or until the object goes out // of scope. // //------------------------------------------------------------------------------ int32 CSimpleSocket::Receive(int32 nMaxBytes) { m_nBytesReceived = 0; //-------------------------------------------------------------------------- // If the socket is invalid then return false. //-------------------------------------------------------------------------- if (IsSocketValid() == false) { return m_nBytesReceived; } //-------------------------------------------------------------------------- // Free existing buffer and allocate a new buffer the size of // nMaxBytes. //-------------------------------------------------------------------------- if ((m_pBuffer != NULL) && (nMaxBytes != m_nBufferSize)) { delete [] m_pBuffer; m_pBuffer = NULL; } //-------------------------------------------------------------------------- // Allocate a new internal buffer to receive data. //-------------------------------------------------------------------------- if (m_pBuffer == NULL) { m_nBufferSize = nMaxBytes; m_pBuffer = new uint8[nMaxBytes]; } SetSocketError(SocketSuccess); switch (m_nSocketType) { m_timer.Initialize(); m_timer.SetStartTime(); //---------------------------------------------------------------------- // If zero bytes are received, then return. If SocketERROR is // received, free buffer and return CSocket::SocketError (-1) to caller. //---------------------------------------------------------------------- case CSimpleSocket::SocketTypeTcp: { do { m_nBytesReceived = RECV(m_socket, (m_pBuffer + m_nBytesReceived), nMaxBytes, m_nFlags); TranslateSocketError(); } while ((GetSocketError() == CSimpleSocket::SocketInterrupted)); break; } case CSimpleSocket::SocketTypeUdp: { uint32 srcSize; srcSize = sizeof(struct sockaddr_in); if (GetMulticast() == true) { do { m_nBytesReceived = RECVFROM(m_socket, m_pBuffer, nMaxBytes, 0, &m_stMulticastGroup, &srcSize); TranslateSocketError(); } while (GetSocketError() == CSimpleSocket::SocketInterrupted); } else { do { m_nBytesReceived = RECVFROM(m_socket, m_pBuffer, nMaxBytes, 0, &m_stClientSockaddr, &srcSize); TranslateSocketError(); } while (GetSocketError() == CSimpleSocket::SocketInterrupted); } break; } default: break; } m_timer.SetEndTime(); TranslateSocketError(); //-------------------------------------------------------------------------- // If we encounter an error translate the error code and return. One // possible error code could be EAGAIN (EWOULDBLOCK) if the socket is // non-blocking. This does not mean there is an error, but no data is // yet available on the socket. //-------------------------------------------------------------------------- if (m_nBytesReceived == CSimpleSocket::SocketError) { if (m_pBuffer != NULL) { delete [] m_pBuffer; m_pBuffer = NULL; } } return m_nBytesReceived; }
/*!\brief Lese-Timeout festlegen * * Mit dieser Funktion kann ein Timeout für Lesezugriffe gesetzt werden. Normalerweise * blockiert eine Leseoperation mit "Read" solange, bis die angeforderten Daten * eingegangen sind (ausser der Socket wurde mit TCPSocket::setBlocking auf "Non-Blocking" * gesetzt). Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus * \p seconds + \p useconds. * \par * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als * Wert für \p seconds und \p useconds aufgerufen werden. * * @param[in] seconds Anzahl Sekunden * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde) * @exception NotConnectedException * @exception InvalidSocketException * @exception BadFiledescriptorException * @exception UnknownOptionException * @exception BadAddressException * @exception InvalidArgumentsException */ void UDPSocket::setTimeoutRead(int seconds, int useconds) { if (!connected) throw NotConnectedException(); struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; PPLSOCKET *s = (PPLSOCKET*) socket; #ifdef WIN32 if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv,sizeof(tv))!=0) { #else if (setsockopt(s->sd, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(tv)) != 0) { #endif throwExceptionFromErrno(errno, "setTimeoutRead"); } } /*!\brief Schreib-Timeout festlegen * * Mit dieser Funktion kann ein Timeout für Schreibzugriffe gesetzt werden. Normalerweise * blockiert eine Schreiboperation mit "Write" solange, bis alle Daten gesendet wurden. * Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus * \p seconds + \p useconds. * \par * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als * Wert für \p seconds und \p useconds aufgerufen werden. * * @param[in] seconds Anzahl Sekunden * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde) * @exception NotConnectedException * @exception InvalidSocketException * @exception BadFiledescriptorException * @exception UnknownOptionException * @exception BadAddressException * @exception InvalidArgumentsException */ void UDPSocket::setTimeoutWrite(int seconds, int useconds) { if (!connected) throw NotConnectedException(); struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; PPLSOCKET *s = (PPLSOCKET*) socket; #ifdef WIN32 if (setsockopt(s->sd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tv,sizeof(tv))!=0) { #else if (setsockopt(s->sd, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(tv)) != 0) { #endif throwExceptionFromErrno(errno, "setTimeoutRead"); } } /*!\brief Auf eingehende Daten warten * * \desc * Diese Funktion prüft, ob Daten eingegangen sind. Ist dies der Fall, * kehrt sie sofort wieder zurück. Andernfalls wartet sie solange, bis * Daten eingehen, maximal aber die mit \p seconds und \p useconds * angegebene Zeitspanne. Falls \p seconds und \p useconds Null sind, und * keine Daten bereitstehen, kehrt die Funktion sofort zurück. * * @param[in] seconds Anzahl Sekunden, die gewartet werden soll * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll * @return Die Funktion gibt \b true zurück, wenn Daten zum Lesen bereitstehen, * sonst \b false. Im Fehlerfall wird eine Exception geworfen. * @exception Diverse */ bool UDPSocket::waitForIncomingData(int seconds, int useconds) { if (!connected) throw NotConnectedException(); PPLSOCKET *s=(PPLSOCKET*)socket; fd_set rset, wset, eset; struct timeval timeout; timeout.tv_sec=seconds; timeout.tv_usec=useconds; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(s->sd,&rset); // Wir wollen nur prüfen, ob was zu lesen da ist int ret=select(s->sd+1,&rset,&wset,&eset,&timeout); if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::waitForIncomingData"); } if (FD_ISSET(s->sd,&eset)) { throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData"); } // Falls Daten zum Lesen bereitstehen, könnte dies auch eine Verbindungstrennung anzeigen if (FD_ISSET(s->sd,&rset)) { char buf[2]; ret=recv(s->sd, buf,1, MSG_PEEK|MSG_DONTWAIT); // Kommt hier ein Fehler zurück? if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::isReadable"); } // Ein Wert von 0 zeigt an, dass die Verbindung getrennt wurde if (ret==0) { throw BrokenPipeException(); } return true; } return false; } /*!\brief Warten, bis der Socket beschreibbar ist * * \desc * Diese Funktion prüft, ob Daten auf den Socket geschrieben werden können. * Ist dies der Fall, kehrt sie sofort wieder zurück. Andernfalls wartet * sie solange, bis der Socket beschrieben werden kann, maximal aber die * mit \p seconds und \p useconds angegebene Zeitspanne. * Falls \p seconds und \p useconds Null sind, und * keine Daten gesendet werden können, kehrt die Funktion sofort zurück. * * @param[in] seconds Anzahl Sekunden, die gewartet werden soll * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll * @return Die Funktion gibt \b true zurück, wenn Daten geschrieben werden können, * sonst \b false. Im Fehlerfall wird eine Exception geworfen. * @exception Diverse * */ bool UDPSocket::waitForOutgoingData(int seconds, int useconds) { if (!connected) throw NotConnectedException(); PPLSOCKET *s=(PPLSOCKET*)socket; fd_set rset, wset, eset; struct timeval timeout; timeout.tv_sec=seconds; timeout.tv_usec=useconds; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(s->sd,&wset); // Wir wollen nur prüfen, ob wir schreiben können int ret=select(s->sd+1,&rset,&wset,&eset,&timeout); if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::waitForOutgoingData"); } if (FD_ISSET(s->sd,&eset)) { throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData"); } if (FD_ISSET(s->sd,&wset)) { return true; } return false; } /*!\brief Bei Lesezugriffen blockieren * * \desc * Durch Aufruf dieser Funktion kann festgelegt werden, ob der Socket bei Lesezugriffen * blockieren soll. Nach dem Öffnen des Sockets ist dieser defaultmäßig so * eingestellt, dass er bei Lesezugriffen solange blockiert (wartet), bis Daten zur * Verfügung stehen. Wird er auf "Non-Blocking" gestellt, kehren die Lese-Funktionen * sofort mit einer Fehlermeldung zurück, wenn noch keine Daten bereitstehen. * * @param[in] value Der Wert "true" setzt den Socket in den Blocking-Modus, was auch der * Default ist. Durch den Wert "false" wird er in den Non-Blocking-Modus gesetzt. * @exception Diverse */ void UDPSocket::setBlocking(bool value) { PPLSOCKET *s=(PPLSOCKET*)socket; if((!s) || (!s->sd)) throw NotConnectedException(); int ret=0; #ifdef _WIN32 u_long v; if (value) { v=0; ret=ioctlsocket(s->sd,FIONBIO,NULL); } else { v=1; ret=ioctlsocket(s->sd,FIONBIO,&v); } if (ret==0) return; throwExceptionFromErrno(errno, "UDPSocket::setBlocking"); #else if (value) ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)&(~O_NONBLOCK)); // Blocking else ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)|O_NONBLOCK);// NON-Blocking if (ret<0) throwExceptionFromErrno(errno, "UDPSocket::setBlocking"); #endif } /*!\brief Socket auf eine IP-Adresse und Port binden * * \desc * Diese Funktion muss aufgerufen werden, bevor man mit CTCPSocket::Listen einen TCP-Server starten kann. Dabei wird mit \p host * die IP-Adresse festgelegt, auf die sich der Server binden soll und mit \p port der TCP-Port. * Es ist nicht möglich einen Socket auf mehrere Adressen zu binden. * * @param[in] host IP-Adresse, Hostname oder "*". Bei Angabe von "*" bindet sich der Socket auf alle * Interfaces des Servers. * @param[in] port Der gewünschte TCP-Port * @exception OutOfMemoryException * @exception ResolverException * @exception SettingSocketOptionException * @exception CouldNotBindToInterfaceException * @exception CouldNotOpenSocketException */ void UDPSocket::bind(const String &host, int port) { //int addrlen=0; if (!socket) { socket=malloc(sizeof(PPLSOCKET)); if (!socket) throw OutOfMemoryException(); PPLSOCKET *s=(PPLSOCKET*)socket; s->sd=0; s->proto=6; s->ipname=NULL; s->port=port; //s->addrlen=0; } #ifdef _WIN32 SOCKET listenfd=0; #else int listenfd=0; #endif PPLSOCKET *s=(PPLSOCKET*)socket; if (s->sd) disconnect(); if (s->ipname) free(s->ipname); s->ipname=NULL; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags=AI_PASSIVE; hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_DGRAM; int on=1; // Prüfen, ob host ein Wildcard ist struct addrinfo *res; if (host.notEmpty()==true && host!="*") { char portstr[10]; sprintf(portstr,"%i",port); int n; if ((n=getaddrinfo(host,portstr,&hints,&res))!=0) { throw ResolverException("%s, %s",(const char*)host,gai_strerror(n)); } struct addrinfo *ressave=res; do { listenfd=::socket(res->ai_family,res->ai_socktype,res->ai_protocol); if (listenfd<0) continue; // Error, try next one #ifdef _WIN32 if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on))!=0) { #else if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))!=0) { #endif freeaddrinfo(ressave); throw SettingSocketOptionException(); } if (::bind(listenfd,res->ai_addr,res->ai_addrlen)==0) { //addrlen=res->ai_addrlen; break; } ::shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif listenfd=0; } while ((res=res->ai_next)!=NULL); freeaddrinfo(ressave); } else { // Auf alle Interfaces binden listenfd=::socket(AF_INET, SOCK_STREAM, 0); if (listenfd>=0) { struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); addr.sin_family = AF_INET; /* bind server port */ if(::bind(listenfd, (struct sockaddr *) &addr, sizeof(addr))!=0) { ::shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif throw CouldNotBindToInterfaceException("Host: *, Port: %d",port); } s->sd=listenfd; connected=1; return; } } if (listenfd<0) { throw CouldNotOpenSocketException("Host: %s, Port: %d",(const char*)host,port); } if (res==NULL) { throw CouldNotBindToInterfaceException("Host: %s, Port: %d",(const char*)host,port); } s->sd=listenfd; connected=1; } /*!\brief Daten schreiben * * \desc * Mit dieser Funktionen werden \p bytes Bytes aus dem Speicherbereich \p buffer an die Gegenstelle * gesendet. * * @param[in] buffer Pointer auf die zu sendenden Daten * @param[in] bytes Anzahl zu sendender Bytes * @return Wenn die Daten erfolgreich geschrieben wurden, gibt die Funktion die Anzahl geschriebener * Bytes zurück. Im Fehlerfall wird eine Exception geworfen. */ size_t UDPSocket::write(const void *buffer, size_t bytes) { if (!connected) throw NotConnectedException(); PPLSOCKET *s = (PPLSOCKET*) socket; if (!buffer) throw InvalidArgumentsException(); size_t BytesWritten = 0; if (bytes) { size_t rest = bytes; ssize_t b = 0; while (rest) { b = ::send(s->sd, (char *) buffer, rest, 0); if (b > 0) { BytesWritten += b; rest -= b; buffer = ((const char*) buffer) + b; } #ifdef WIN32 if (b==SOCKET_ERROR) { #else if (b < 0) { #endif if (errno == EAGAIN) { waitForOutgoingData(0, 100000); } else { throwExceptionFromErrno(errno, "UDPSocket::write"); } } } } return BytesWritten; } size_t UDPSocket::write(const String &str, size_t bytes) { if (bytes>0 && bytes<=str.size()) { return write(str.getPtr(),bytes); } return write(str.getPtr(),str.size()); } size_t UDPSocket::write(const WideString &str, size_t bytes) { if (bytes>0 && bytes<=str.byteLength()) { return write(str.getPtr(),bytes); } return write(str.getPtr(),str.byteLength()); } size_t UDPSocket::write(const ByteArrayPtr &bin, size_t bytes) { if (bytes>0 && bytes<=bin.size()) { return write(bin.ptr(),bytes); } return write(bin.ptr(),bin.size()); } size_t UDPSocket::writef(const char *fmt, ...) { if (!fmt) throw IllegalArgumentException(); String str; va_list args; va_start(args, fmt); str.vasprintf(fmt,args); va_end(args); return write(str); } #ifdef TODO void UDPSocket::setTimeoutRead(int seconds, int useconds) /*! \brief Timeout setzen * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird der Timeout für das Empfangen von Daten gesetzt. * * \param seconds Anzahl Sekunden * \param useconds Anzahl Millisekunden * \note Diese Funktion hat zur Zeit noch keine Auswirkungen * \since Wurde mit Version 6.0.19 eingeführt */ { timeout_sec=seconds; timeout_usec=useconds; } #endif #ifdef TODO size_t UDPSocket::sendTo(const String &host, int port, const String &buffer) /*! \brief UDP-Packet verschicken * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt. * * \param host Der Name oder die IP-Adresse des Zielrechners * \param port Der Port des Zielrechners * \param buffer Ein Pointer auf eine String-Klasse, die die zu sendenden Daten enthält * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { return sendTo(host,port,(const void *)buffer.getPtr(),buffer.len()); } size_t UDPSocket::sendTo(const String &host, int port, const void *buffer, size_t bytes) /*! \brief UDP-Packet verschicken * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt. * * \param host Der Name oder die IP-Adresse des Zielrechners * \param port Der Port des Zielrechners * \param buffer Ein Pointer auf den Puffer, der die zu sendenden Daten enthält * \param bytes Die Anzahl Bytes im Puffer, die gesendet werden sollen * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { if (!host) { ppl6::SetError(194,"int UDPSocket::SendTo(==> char *host <== , int port, void *buffer, int bytes)"); return -1; } if (!port) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, ==> int port <== , void *buffer, int bytes)"); return -1; } if (!buffer) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, ==> void *buffer <== , int bytes)"); return -1; } if (bytes<0) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, void *buffer, ==> int bytes <== )"); return -1; } ppl6::CAssocArray res, *a; ppl6::CBinary *bin; if (!ppl6::GetHostByName(host,&res)) return -1; a=res.GetFirstArray(); //a->List(); int domain, type, protocol; domain=ppl6::atoi(a->Get("ai_family")); type=ppl6::atoi(a->Get("ai_socktype")); //protocol=ppl6::atoi(a->Get("ai_protocol")); struct protoent *proto=getprotobyname("UDP"); if (!proto) { ppl6::SetError(395); return -1; } protocol=proto->p_proto; bin=a->GetBinary("ai_addr"); //a->List(); const struct sockaddr *to=(const struct sockaddr *)bin->GetPtr(); ((sockaddr_in*)to)->sin_port=htons(port); PPLSOCKET *s=(PPLSOCKET*)socket; if (!s) { socket=malloc(sizeof(PPLSOCKET)); s=(PPLSOCKET*)socket; s->sd=-1; } else if ((int)s->sd>-1) { ppl_closesocket(s->sd); } s->sd=::socket(domain,SOCK_DGRAM,protocol); //sockfd=::socket(AF_INET,SOCK_DGRAM,0); if (s->sd<0) { SetSocketError(); return -1; } #ifdef _WIN32 int ret=::sendto(s->sd,(const char*)buffer,bytes,0,to,bin->GetSize()); #else ssize_t ret=::sendto(s->sd,(const void*)buffer,(size_t)bytes,0,to,(socklen_t) bin->GetSize()); #endif if (ret<0) { printf ("ret: %i\n",(int)ret); SetSocketError(); return -1; } //close(sockfd); return ret; } int UDPSocket::RecvFrom(CString &buffer, int maxlen) /*! \brief UDP-Packet empfangen * * \header \#include <ppl6.h> * \desc * Diese Funktion wartet auf ein UDP-Packet * * \param buffer Ein Pointer auf eine String-Klasse, in die die Daten geschrieben werden sollen * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { char *b=(char*)malloc(maxlen+1); if (!b) { SetError(2); return 0; } int ret=RecvFrom((void*)b,maxlen); buffer.ImportBuffer(b,maxlen); return ret; }
void CSocket::SetSocketError(void) { int nError = WSAGetLastError(); switch (nError) { case EXIT_SUCCESS: SetSocketError(SocketEnum::Success); break; case WSAEBADF: case WSAENOTCONN: SetSocketError(SocketEnum::Notconnected); break; case WSAEINTR: SetSocketError(SocketEnum::Interrupted); break; case WSAEACCES: case WSAEAFNOSUPPORT: case WSAEINVAL: case WSAEMFILE: case WSAENOBUFS: case WSAEPROTONOSUPPORT: SetSocketError(SocketEnum::InvalidSocket); break; case WSAECONNREFUSED : SetSocketError(SocketEnum::ConnectionRefused); break; case WSAETIMEDOUT: SetSocketError(SocketEnum::Timedout); break; case WSAEINPROGRESS: SetSocketError(SocketEnum::Einprogress); break; case WSAECONNABORTED: SetSocketError(SocketEnum::ConnectionAborted); break; case WSAEWOULDBLOCK: SetSocketError(SocketEnum::Ewouldblock); break; case WSAENOTSOCK: SetSocketError(SocketEnum::InvalidSocket); break; case WSAECONNRESET: SetSocketError(SocketEnum::ConnectionReset); break; case WSANO_DATA: SetSocketError(SocketEnum::InvalidAddress); break; case WSAEADDRINUSE: SetSocketError(SocketEnum::AddressInUse); break; case WSAEFAULT: SetSocketError(SocketEnum::InvalidPointer); break; default: SetSocketError(SocketEnum::UnknownError); break; } }
bool CSocket::ShutDown(SocketEnum::ShutdownMode mode) { SocketEnum::SocketError nRetVal = (SocketEnum::SocketError)shutdown(csocket, SocketEnum::Both); SetSocketError(); return (nRetVal == SocketEnum::Success) ? true: false; }