DWORD WINAPI TcpServer::RecvThreadProc(LPVOID lpParameter) { TcpServer* _this=(TcpServer*)lpParameter; TransparentWnd *win=(TransparentWnd *)_this->winHandler; int size=0; //std::stringstream ss; int count=0; char* s=NULL; bool startReceive=false; int retry=0; //开始接受数据,等待 for(;;) { char recvBuf[40960] = {0}; int l=recv(_this->curSocket,recvBuf,40960,0); if(l==0) { ++retry; if(retry>3){ if(!startReceive){ size=0; if(s!=NULL){ delete s; s=NULL; } count=0; waitForConnect(lpParameter); break; retry=0; } } } else{ if(size==0&&l==4){ int *b= (int*)recvBuf; size=(int)(*b); if(s!=NULL){ delete s; s=NULL; } s=new char[size+1]; s[size]=0; } else if(s!=NULL&&size>0){ for(int i=count,j=0;i<count+l&&i<size;++i,++j){ s[i]=recvBuf[j]; } count+=l; if(count>=size){ win->RecieveMessage(TCPMESSAGE,s,0,0); size=0; count=0; } } } } return 0; }
int CCONV stream_server_connect(const char *dest, const char *svcname, int *fdp, int *cancelSocket, char *errdesc, int errdesclen) { struct addrinfo hints, *res, *res0 = NULL; int err, cancelled = 0; SOCKET s = INVALID_SOCKET; int tmpSock[2]; int cancelRecvSocket = INVALID_SOCKET; #ifdef _WINDOWS u_long nNonBlocking = TRUE; #endif memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo(dest, svcname, &hints, &res0)) != 0) { if (errdesc) snprintf(errdesc, errdesclen, "getaddrinfo: %s", gai_strerror(err)); freeaddrinfo(res0); return 0; } //setup cancel socket err = socketpair(AF_UNIX, SOCK_STREAM, 0, tmpSock); if (err < 0) { err = errno; } else { *cancelSocket = tmpSock[0]; cancelRecvSocket = tmpSock[1]; } for (res = res0; res; res = res->ai_next) { if(cancelled) break; // sometimes on mac, we get 0.0.0.0 ??!! - just ignore it if(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr == 0) { continue; } s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); #ifndef _WINDOWS if (s < 0) { #else if (s == INVALID_SOCKET) { #endif SET_ERRDESC(errdesc, errdesclen); continue; } //Make the socket non-blocking #ifndef _WINDOWS if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) { SET_ERRDESC(errdesc, errdesclen); s = INVALID_SOCKET; continue; } #else if (ioctlsocket(s, FIONBIO, (u_long FAR *) & nNonBlocking)) { s = INVALID_SOCKET; continue; } #endif if((err = connect(s, res->ai_addr, (int) res->ai_addrlen)) != 0) { //Connection in progress - wait for completion or cancelation #ifndef _WINDOWS if(errno == EINPROGRESS) #else err = WSAGetLastError(); if(err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) #endif { err = waitForConnect(s, cancelRecvSocket); // Not cancelled, so must have either connected or failed. // Check to see if we're connected by calling getpeername. if (err == 0) { socklen_t len = sizeof(struct sockaddr); struct sockaddr name; err = getpeername(s, &name, &len); // The connection failed. Get the error associated with // the connection attempt. if (err < 0) { int tmpErr; #ifdef _WINDOWS err = WSAGetLastError(); #endif len = sizeof(tmpErr); err = getsockopt(s, SOL_SOCKET, SO_ERROR, &tmpErr, &len); if (err < 0) { #ifdef _WINDOWS err = WSAGetLastError(); #else err = errno; #endif } else { assert(tmpErr != 0); err = tmpErr; } } //connection good else break; } //cancelled else if(err==ECANCELED) { cancelled = 1; } #ifdef _WINDOWS WSASetLastError(err); #else errno = err; #endif } //Error SET_ERRDESC(errdesc, errdesclen); #ifndef _WINDOWS close(s); #else closesocket(s); #endif s = INVALID_SOCKET; continue; } break; } //cleanup cancel socket - not needed anymore if (tmpSock[0] != -1) #ifndef _WINDOWS close(tmpSock[0]); #else closesocket(tmpSock[0]); #endif if (tmpSock[1] != -1) #ifndef _WINDOWS close(tmpSock[1]); #else closesocket(tmpSock[1]); #endif *cancelSocket = INVALID_SOCKET; #ifndef _WINDOWS if (s < 0) { #else if (s == INVALID_SOCKET) { #endif SET_ERRDESC(errdesc, errdesclen); freeaddrinfo(res0); return 0; } if (fdp) *fdp = s; freeaddrinfo(res0); return 1; } /* * Accepts a TCP connection on a given port and invokes the given * callback to handle it. This is where the main server thread sits. */ int stream_server_accept(int port, void(*clfunc)(int fd, const char *addr, int port), char *errdesc, int errdesclen) { struct sockaddr_in sin = { 0 }; struct sockaddr_in cin = { 0 }; const int opt = 1; socklen_t cl; char *addr; int fd; int s; if (!(s = (int)socket(PF_INET, SOCK_STREAM, 0))) { SET_ERRDESC(errdesc, errdesclen); return 0; } setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof (opt)); #ifdef _MACOSX setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof (opt)); #endif sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = INADDR_ANY; if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) != 0) { SET_ERRDESC(errdesc, errdesclen); return 0; } if (listen(s, 5) != 0) { SET_ERRDESC(errdesc, errdesclen); return 0; } for (;;) { cl = sizeof(cin); while ((fd = (int)accept(s, (struct sockaddr *)&cin, &cl)) < 0 && errno == EAGAIN) ; if (fd < 0) { SET_ERRDESC(errdesc, errdesclen); return 0; } setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&opt, sizeof (opt)); #ifdef _MACOSX setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof (opt)); #endif addr = strdup(inet_ntoa(cin.sin_addr)); clfunc(fd, addr, ntohs(cin.sin_port)); free(addr); addr = NULL; } /*NOTREACHED*/ } int pu_write(int fd, const void *buf, unsigned int len, char *errdesc, int edlen) { static pthread_mutex_t *writelock = 0; int res = 0; int olen = len; if (fd == -1) return len; if (!writelock) { if (!(writelock = malloc(sizeof (*writelock)))) return 0; pthread_mutex_init(writelock, NULL); } pthread_mutex_lock(writelock); do { if (res > 0) { #ifdef _WINDOWS (unsigned char *)buf += res; #else buf += res; #endif len -= res; } if (len) { tryagain: res = send(fd, buf, len, MSG_NOSIGNAL); //Error if(res == -1) { #ifdef _WINDOWS switch(WSAGetLastError()) { //non-blocking, try again case WSAEWOULDBLOCK: SLEEP(10); goto tryagain; //any other error, don't try again default: break; } #else switch(errno) { //Interrupted, try again case EINTR: //non-blocking, try again case EAGAIN: SLEEP(10); goto tryagain; //any other error, don't try again default: break; } #endif } } else res = olen; } while (len && res >= 0); pthread_mutex_unlock(writelock); if (res != olen) { SET_ERRDESC(errdesc, edlen); return 0; } else return 1; } int pu_read(int fd, void *buf, unsigned int len, char *errdesc, int edlen) { int res=0, err=0; if (fd == -1) return 0; tryagain: res = recv(fd, buf, len, 0); //Error if(res == -1) { #ifdef _WINDOWS switch(WSAGetLastError()) { //non-blocking, try again case WSAEWOULDBLOCK: SLEEP(10); goto tryagain; //any other error, don't try again default: err = WSAGetLastError(); break; } #else switch(errno) { //Interrupted, try again case EINTR: //non-blocking, try again case EAGAIN: SLEEP(10); goto tryagain; //any other error, don't try again default: err = errno; break; } #endif } if (res <= 0) { SET_ERRDESC(errdesc, edlen); return 0; } else return res; } int pu_close(int fd, char *errdesc, int edlen) { int res=0; if(fd == -1) return 0; #ifndef _WINDOWS res = close(fd); #else res = closesocket(fd); #endif SET_ERRDESC(errdesc, edlen); return res; }