bool PeerConnector::ConnectUDP(const PEER_ADDRESS& addr, const PeerConnectParam& param) { if (m_LiveInfo.TransferMethod == TRANSFER_TCP) { return ConnectTCP(addr, 0, param); // 用于测试纯tcp的情况 } if ( addr.UdpPort == 0 ) return false; if (CheckConnected(addr, param.IsVIP)) { VIEW_INFO("CPeerManager::ConnectToRemote CheckConnected " << addr << " failed"); return false; } const PEER_ADDRESS& localAddr = m_NetInfo->Address; if (addr.IP == localAddr.IP && addr.UdpPort == localAddr.UdpPort) { //LIVE_ASSERT(false); VIEW_ERROR("ConnectUDP ignore myself " << addr); return false; } return m_UDPConnector->Connect(addr, param); }
DWORD WINAPI ConnectThrProc(LPVOID lpParam) { #else void* ConnectThrProc(void* lpParam) { #endif int EndThread = 0; CLITCP* pCLITCP = (CLITCP*)lpParam; int connected = 0; do { memcpy_ts(&connected, &pCLITCP->connected, sizeof(int), &pCLITCP->CSconnected); // Thread-safe copy if (connected != 1) { // The client is not connected to the server, trying to connect or reconnect StopTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf); if ( (InitTCP(&pCLITCP->ConnectSocket, pCLITCP->address, pCLITCP->port, &pCLITCP->addrinf) == EXIT_SUCCESS)&& // (SetSockOptTCP(pCLITCP->ConnectSocket, 1, 10000) == EXIT_SUCCESS)&& // Setting timeouts on the client socket (ConnectTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf) == EXIT_SUCCESS)//&& // (SetSockOptTCP(pCLITCP->ConnectSocket, 1, 10000) == EXIT_SUCCESS) // Setting timeouts on the client socket ) { fprintf(stdout, "Connection successful\n"); connected = 1; memcpy_ts(&pCLITCP->connected, &connected, sizeof(int), &pCLITCP->CSconnected); // Thread-safe copy } else fprintf(stdout, "Unable to connect\n"); } mSleep(1000); memcpy_ts(&EndThread, &pCLITCP->EndThread, sizeof(int), &pCLITCP->CSEndThread); // Thread-safe copy } while(!EndThread); return 0; }
/* Connects to the server until it succeeds. This function should not block more than 10 s. If the client can not connect immediately, a thread keeps trying to connect to the server until it succeeds or StopCLITCP() is called. A return value of EXIT_SUCCESS does not necessary mean that the client is connected. Use GetStatusCLITCP() to verify it. CLITCP* pCLITCP : (IN,OUT) pointer to the data structure representing the client Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error */ int ConnectCLITCP(CLITCP* pCLITCP) { int EndThread = 0; if ((pCLITCP == NULL) || (pCLITCP->initialized != 1)) { return EXIT_FAILURE; } memcpy_ts(&EndThread, &pCLITCP->EndThread, sizeof(int), &pCLITCP->CSEndThread); // Thread-safe copy if (EndThread == 0) { // A thread is already running and only one thread should be running at a time return EXIT_FAILURE; // This function should not have been called } if (ConnectTCP(pCLITCP->ConnectSocket, &pCLITCP->addrinf) == EXIT_SUCCESS) { pCLITCP->connected = 1; // Notifies that the client is currently connected fprintf(stdout, "Connection successful\n"); } else { pCLITCP->connected = 0; // Notifies that the client is currently not connected fprintf(stdout, "Unable to connect\n"); } pCLITCP->EndThread = 0; // Notifies that a thread should be running if (CreateDefaultThread(ConnectThrProc, pCLITCP, &pCLITCP->ThrId) != EXIT_SUCCESS) { pCLITCP->EndThread = 1; // Notifies that no thread is running as its creation failed return EXIT_FAILURE; } return EXIT_SUCCESS; }
//------------------------------------------------------------------------------ // // 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; }
bool PeerConnector::Connect(const PEER_ADDRESS& addr, const PeerConnectParam& param) { if (param.ConnectFlags == IPPOOL_CONNECT_NORMAL) { return ConnectTCP(addr, 0, param); } else if (param.ConnectFlags == IPPOOL_CONNECT_80) { return ConnectTCP(addr, 80, param); } else if (param.ConnectFlags == IPPOOL_CONNECT_UDPT) { return ConnectUDP(addr, param); } else { // 如果默认的话,就直接转向 IPPOOL_CONNECT_ LIVE_ASSERT(param.ConnectFlags == IPPOOL_CONNECT_NONE); return ConnectUDP(addr, param); } }
DWORD WINAPI ConnectThrProc(LPVOID lpParam) { #else void* ConnectThrProc(void* lpParam) { #endif int EndThread = 0; CLITCP* pCLITCP = (CLITCP*)lpParam; int connected = 0; do { // Checks whether the client is currently connected or not memcpy_ts(&connected, &pCLITCP->connected, sizeof(int), &pCLITCP->CSconnected); // Thread-safe copy if (connected != 1) { // The client is not connected to the server, trying to connect or reconnect ShutdownTCP(&pCLITCP->ConnectSocket, SD_BOTH); DestroySocketTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf); if ( (CreateSocketTCP(&pCLITCP->ConnectSocket, pCLITCP->address, pCLITCP->port, &pCLITCP->addrinf) == EXIT_SUCCESS)&& (SetSockOptTCP(pCLITCP->ConnectSocket, 1, 10000) == EXIT_SUCCESS)&& // Setting timeouts on the client socket (ConnectTCP(pCLITCP->ConnectSocket, &pCLITCP->addrinf) == EXIT_SUCCESS) ) { connected = 1; memcpy_ts(&pCLITCP->connected, &connected, sizeof(int), &pCLITCP->CSconnected); // Thread-safe copy fprintf(stdout, "Connection successful\n"); } else { fprintf(stdout, "Unable to connect\n"); } } mSleep(1000); memcpy_ts(&EndThread, &pCLITCP->EndThread, sizeof(int), &pCLITCP->CSEndThread); // Thread-safe copy } while(!EndThread); return 0; }
main(int, char **argv) { #ifdef _WIN32 WSADATA wd; if( WSAStartup( 0x0101, &wd ) ) { fputs("Winsock initialization failure.", stderr); return -1; } #endif char *szServer = NULL; char *szName = NULL; char *szPassword = NULL; puts("POPMAN, by Olof Lagerkvist.\r\n" "http://www.ltr-data.se"); #ifdef _WIN32 char cFileNameBuf[MAX_PATH]; if (GetModuleFileName(NULL, cFileNameBuf, sizeof cFileNameBuf)) { // About message from file version resource WFileVerInfo *pfvi = new WFileVerInfo(cFileNameBuf); char *pcDescr = (char*)pfvi->QueryValue(); char *pcVer = (char*)pfvi->QueryValue("\\StringFileInfo\\040904E4\\FileVersion"); if ((pcDescr != NULL) & (pcVer != NULL)) printf("%s ver %s, compile date %s\n", pcDescr, pcVer, __DATE__); else printf("Compile date: %s\n", __DATE__); delete pfvi; } #else printf("Compile date: %s\n", __DATE__); #endif if (argv[1]) { szName = strtok(argv[1], "@"); szServer = strtok(NULL, ""); strtok(szName, ":"); szPassword = strtok(NULL, ""); } char cServer[MAX_PATH] = ""; if (szServer == NULL) { printf("POP server name: "); fgets(cServer, sizeof cServer, stdin); cServer[strlen(cServer)-1] = 0; if (cServer[0] == '\x00') return 1; szServer = cServer; } // Connect HANDLE s = (HANDLE)ConnectTCP(szServer, htons(110)); if (s == INVALID_HANDLE_VALUE) { h_perror("connect() failed"); return -1; } char cBuf[MAX_PATH] = ""; do { if (LineRecv((HANDLE)s, cBuf, sizeof cBuf) == 0) { fputs("Unknown response from server.\r\n", stderr); return 1; } puts(cBuf); if (cBuf[0] == '-') return 1; } while (cBuf[0] != '+'); char cName[MAX_PATH] = ""; if (szName == NULL) { printf("User name: "); fgets(cName, sizeof cName, stdin); cName[strlen(cName)-1] = 0; szName = cName; } puts("Sending user name..."); if (!StrSend(s, "USER ")) return 1; if (!StrSend(s, szName)) return 1; if (!StrSend(s, "\r\n")) return 1; do { if (LineRecv(s, cBuf, sizeof cBuf) == 0) return 1; puts(cBuf); if (cBuf[0] == '-') return 1; } while (cBuf[0] != '+'); char cPassword[MAX_PATH] = ""; if (szPassword == NULL) { printf("Password: "******"\x08 \x08", stdout); --ptr; } continue; } fputc('*', stdout); ++ptr; } wcStdIn.SetMode(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT); puts(""); #else fgets(cPassword, sizeof cPassword, stdin); cPassword[strlen(cPassword)-1] = 0; #endif szPassword = cPassword; } puts("Sending password..."); if (!StrSend(s, "PASS ")) return 1; if (!StrSend(s, szPassword)) return 1; if (!StrSend(s, "\r\n")) return 1; do { if (LineRecv(s, cBuf, sizeof cBuf) == 0) return 1; puts(cBuf); if (cBuf[0] == '-') return 1; } while (cBuf[0] != '+'); /* puts("Server: '" << szServer << "'\r\n" "User name: '" << szName << "'\r\n" "Password: '******'"); */ if (!StrSend(s, "LIST\r\n")) return 1; if (LineRecv(s, cBuf, sizeof cBuf) == 0) return 1; puts(cBuf); int iMailCount = 0; for(; ; iMailCount++) { Sleep(0); if (LineRecv(s, cBuf, sizeof cBuf) == 0) return 1; if (cBuf[0] == '.') break; strtok(cBuf, " "); char *msg = strtok(NULL, ""); printf("Message no %s: %s bytes.\n", cBuf, msg); } if (iMailCount == 0) { puts("No messages in mailbox."); return 0; } for(;;) { puts("Type the number of the message you want to delete,\r\n" "or exit when done."); Sleep(0); fgets(cBuf, sizeof cBuf, stdin); cBuf[strlen(cBuf)-1] = 0; if (cBuf[0] == '\x00') break; if (strcmpi(cBuf, "EXIT") == 0) break; printf("Deleting message no %s\n", cBuf); if (!StrSend(s, "DELE ")) return 1; if (!StrSend(s, cBuf)) return 1; if (!StrSend(s, "\r\n")) return 1; do { if (LineRecv(s, cBuf, sizeof cBuf) == 0) return 1; puts(cBuf); if (cBuf[0] == '-') break; } while (cBuf[0] != '+'); } StrSend(s, "QUIT\r\n"); while (LineRecv(s, cBuf, sizeof cBuf)) puts(cBuf); }
/* Initializes the TCP client. CLITCP* pCLITCP : (IN,OUT) pointer to the data structure representing the client char* address : (IN) server address to connect char* port : (IN) server port to connect Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error */ int InitCLITCP(CLITCP* pCLITCP, char* address, char* port) { int EndThread = 1; if((pCLITCP == NULL) || (pCLITCP->initialized == 1)) { return EXIT_FAILURE; } pCLITCP->address = (char*)calloc(strlen(address)+1, sizeof(char)); sprintf(pCLITCP->address, "%s", address); pCLITCP->port = (char*)calloc(strlen(port)+1, sizeof(char)); sprintf(pCLITCP->port, "%s", port); pCLITCP->ConnectSocket = INVALID_SOCKET; pCLITCP->addrinf = NULL; pCLITCP->EndThread = 0; pCLITCP->connected = 0; if ( (InitTCP(&pCLITCP->ConnectSocket, pCLITCP->address, pCLITCP->port, &pCLITCP->addrinf) == EXIT_SUCCESS)&& // (SetSockOptTCP(pCLITCP->ConnectSocket, 1, 10000) == EXIT_SUCCESS)&& // Setting timeouts on the client socket (ConnectTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf) == EXIT_SUCCESS)//&& // (SetSockOptTCP(pCLITCP->ConnectSocket, 1, 10000) == EXIT_SUCCESS) // Setting timeouts on the client socket ) { fprintf(stdout, "Connection successful\n"); pCLITCP->connected = 1; } else fprintf(stdout, "Unable to connect\n"); if (InitCriticalSection(&pCLITCP->CSEndThread) != EXIT_SUCCESS) { StopTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf); free(pCLITCP->address);pCLITCP->address = NULL; free(pCLITCP->port);pCLITCP->port = NULL; return EXIT_FAILURE; } if (InitCriticalSection(&pCLITCP->CSconnected) != EXIT_SUCCESS) { DelCriticalSection(&pCLITCP->CSEndThread); StopTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf); free(pCLITCP->address);pCLITCP->address = NULL; free(pCLITCP->port);pCLITCP->port = NULL; return EXIT_FAILURE; } if (CreateDefaultThread(ConnectThrProc, pCLITCP, &pCLITCP->ThrId) != EXIT_SUCCESS) { DelCriticalSection(&pCLITCP->CSEndThread); DelCriticalSection(&pCLITCP->CSconnected); StopTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf); free(pCLITCP->address);pCLITCP->address = NULL; free(pCLITCP->port);pCLITCP->port = NULL; return EXIT_FAILURE; } if (SetThreadDefaultPriority(pCLITCP->ThrId, THREAD_PRIORITY_NORMAL) != EXIT_SUCCESS) { EndThread = 1; memcpy_ts((char*)&pCLITCP->EndThread, (char*)&EndThread, sizeof(int), &pCLITCP->CSEndThread); // Thread-safe copy WaitForThread(pCLITCP->ThrId); DelCriticalSection(&pCLITCP->CSEndThread); DelCriticalSection(&pCLITCP->CSconnected); StopTCP(&pCLITCP->ConnectSocket, &pCLITCP->addrinf); free(pCLITCP->address);pCLITCP->address = NULL; free(pCLITCP->port);pCLITCP->port = NULL; return EXIT_FAILURE; } pCLITCP->initialized = 1; return EXIT_SUCCESS; }
DWORD CALLBACK Thread() { IMDPROXY_CONNECT_REQ ConnectReq; KdPrint(("ImDskSvc: Thread created.%n")); if (Overlapped.BufRecv(hPipe, &ConnectReq.request_code, sizeof ConnectReq.request_code) != sizeof ConnectReq.request_code) { KdPrintLastError(("Overlapped.BufRecv() failed")); delete this; return 0; } if (ConnectReq.request_code != IMDPROXY_REQ_CONNECT) { delete this; return 0; } if (Overlapped.BufRecv(hPipe, ((PUCHAR)&ConnectReq) + sizeof(ConnectReq.request_code), sizeof(ConnectReq) - sizeof(ConnectReq.request_code)) != sizeof(ConnectReq) - sizeof(ConnectReq.request_code)) { KdPrintLastError(("Overlapped.BufRecv() failed")); delete this; return 0; } if ((ConnectReq.length == 0) | (ConnectReq.length > 520)) { KdPrint(("ImDskSvc: Bad connection string length received (%1!u!).%n", ConnectReq.length)); delete this; return 0; } WCRTMem<WCHAR> ConnectionString((size_t)ConnectReq.length + 2); if (!ConnectionString) { KdPrintLastError(("malloc() failed")); delete this; return 0; } if (Overlapped.BufRecv(hPipe, ConnectionString, (DWORD)ConnectReq.length) != ConnectReq.length) { KdPrintLastError(("Overlapped.BufRecv() failed")); delete this; return 0; } IMDPROXY_CONNECT_RESP connect_resp = { 0 }; ConnectionString[ConnectReq.length / sizeof *ConnectionString] = 0; // Split server connection string and string that should be sent to server // for server side connection to specific image file. LPWSTR path_part = wcsstr(ConnectionString, L"://"); if (path_part != NULL) { path_part[0] = 0; path_part++; } HANDLE hTarget; switch (IMDISK_PROXY_TYPE(ConnectReq.flags)) { case IMDISK_PROXY_TYPE_COMM: { LPWSTR FileName = wcstok(ConnectionString, L": "); KdPrint(("ImDskSvc: Connecting to '%1!ws!'.%n", FileName)); hTarget = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hTarget == INVALID_HANDLE_VALUE) { connect_resp.error_code = GetLastError(); KdPrintLastError(("CreateFile() failed")); Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } LPWSTR DCBAndTimeouts = wcstok(NULL, L""); if (DCBAndTimeouts != NULL) { DCB dcb = { 0 }; COMMTIMEOUTS timeouts = { 0 }; if (DCBAndTimeouts[0] == L' ') ++DCBAndTimeouts; KdPrint(("ImDskSvc: Configuring '%1!ws!'.%n", DCBAndTimeouts)); GetCommState(hTarget, &dcb); GetCommTimeouts(hTarget, &timeouts); BuildCommDCBAndTimeouts(DCBAndTimeouts, &dcb, &timeouts); SetCommState(hTarget, &dcb); SetCommTimeouts(hTarget, &timeouts); } KdPrint(("ImDskSvc: Connected to '%1!ws!' and configured.%n", FileName)); break; } case IMDISK_PROXY_TYPE_TCP: { LPWSTR ServerName = wcstok(ConnectionString, L":"); LPWSTR PortName = wcstok(NULL, L""); if (PortName == NULL) PortName = L"9000"; KdPrint(("ImDskSvc: Connecting to '%1!ws!:%2!ws!'.%n", ServerName, PortName)); hTarget = (HANDLE)ConnectTCP(ServerName, PortName); if (hTarget == INVALID_HANDLE_VALUE) { connect_resp.error_code = GetLastError(); KdPrintLastError(("ConnectTCP() failed")); Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } bool b = true; setsockopt((SOCKET)hTarget, IPPROTO_TCP, TCP_NODELAY, (LPCSTR)&b, sizeof b); KdPrint(("ImDskSvc: Connected to '%1!ws!:%2!ws!' and configured.%n", ServerName, PortName)); break; } default: KdPrint(("ImDskSvc: Unsupported connection type (%1!#x!).%n", IMDISK_PROXY_TYPE(ConnectReq.flags))); connect_resp.error_code = (ULONGLONG)-1; Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } // Connect to requested server side image path if (path_part != NULL) { size_t path_size = wcslen(path_part) << 1; size_t req_size = sizeof(IMDPROXY_CONNECT_REQ) + path_size; WCRTMem<IMDPROXY_CONNECT_REQ> open_request(req_size); if (!open_request) { KdPrintLastError(("malloc() failed")); connect_resp.error_code = (ULONGLONG)-1; Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } ZeroMemory(open_request, req_size); open_request->request_code = IMDPROXY_REQ_CONNECT; open_request->length = path_size; memcpy(open_request + 1, path_part, path_size); if (!Overlapped.BufSend(hTarget, open_request, (DWORD)req_size)) { KdPrintLastError(("Failed to send connect request to server")); connect_resp.error_code = (ULONGLONG)-1; Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } open_request.Free(); if (Overlapped.BufRecv(hTarget, &connect_resp, sizeof connect_resp) != sizeof connect_resp) { connect_resp.object_ptr = NULL; if (connect_resp.error_code == 0) { connect_resp.error_code = (ULONGLONG)-1; } Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } } ConnectionString.Free(); HANDLE hDriver = CreateFile(IMDISK_CTL_DOSDEV_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { connect_resp.error_code = GetLastError(); KdPrintLastError(("Opening ImDiskCtl device failed")); CloseHandle(hTarget); Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } DWORD dw; if (!DeviceIoControl(hDriver, IOCTL_IMDISK_REFERENCE_HANDLE, &hTarget, #pragma warning(suppress: 28132) sizeof hTarget, &connect_resp.object_ptr, sizeof connect_resp.object_ptr, &dw, NULL)) { connect_resp.error_code = GetLastError(); KdPrintLastError(("IOCTL_IMDISK_REFERENCE_HANDLE failed")); CloseHandle(hDriver); CloseHandle(hTarget); Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); delete this; return 0; } CloseHandle(hDriver); Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp); // This will fail when driver closes the pipe, but that just indicates that // we should shut down this connection. Overlapped.BufRecv(hPipe, &dw, sizeof dw); KdPrint(("ImDskSvc: Cleaning up.%n")); CloseHandle(hTarget); delete this; return 1; }
/* 接続ごとにスレッドを作るように改良した方がいいと思われます */ void CTsNetworkSender::SendMain() { for (int i = 0; i <= m_MaxConnectRetries; i++) { if (ConnectTCP()) break; if (m_EndSendingEvent.Wait(m_ConnectRetryInterval) != WAIT_TIMEOUT) return; } for (auto i = m_SockList.begin(); i != m_SockList.end(); ++i) { if (i->Type == SOCKET_TCP && !i->bConnected) { TraceAddress(CTracer::TYPE_ERROR, TEXT("%s:%d に接続できません。"), i->AddrList); } } CMediaData SendData; DWORD Count = 0; DWORD Wait = m_SendWait; m_bEnableQueueing = true; do { static const DWORD TCP_HEADER_SIZE = 2 * sizeof(DWORD); SendData.SetSize(TCP_HEADER_SIZE); if (GetStream(&SendData, &Wait)) { const DWORD DataOctets = SendData.GetSize() - TCP_HEADER_SIZE; DWORD *pHeader = (DWORD*)SendData.GetData(); pHeader[0] = Count; pHeader[1] = DataOctets; for (auto i = m_SockList.begin(); i != m_SockList.end(); ++i) { if (i->Type == SOCKET_UDP) { if (i->sock != INVALID_SOCKET) { int Result = ::sendto( i->sock, (const char*)SendData.GetData() + TCP_HEADER_SIZE, DataOctets, 0, i->addr->ai_addr, (int)i->addr->ai_addrlen); if (Result != SOCKET_ERROR) { i->SentBytes += Result; } #ifdef _DEBUG else { TRACE(TEXT("sendto() error %d\n"), ::WSAGetLastError()); } #endif } } else { if (i->bConnected) { const char *pData = (const char*)SendData.GetData(); int Size; if (m_bTcpPrependHeader) { Size = (int)SendData.GetSize(); } else { pData += TCP_HEADER_SIZE; Size = DataOctets; } const int MaxRetries = m_TcpMaxSendRetries; for (int j = 0; j < 1 + MaxRetries; j++) { int Result = ::send(i->sock, pData, Size, 0); if (Result != SOCKET_ERROR) { i->SentBytes += Result; break; } if (j == MaxRetries) { TRACE(TEXT("send() error %d\n"), ::WSAGetLastError()); break; } int Error = ::WSAGetLastError(); if (Error != WSAEWOULDBLOCK) { TRACE(TEXT("send() error %d\n"), Error); break; } Result = ::WSAWaitForMultipleEvents(1, &i->Event, FALSE, 1000, FALSE); if (Result != WSA_WAIT_EVENT_0) break; WSANETWORKEVENTS Events; Result = ::WSAEnumNetworkEvents(i->sock, i->Event, &Events); if (Result == SOCKET_ERROR || (Events.lNetworkEvents & FD_WRITE) == 0) break; } //Count++; } } } Count++; } } while (m_EndSendingEvent.Wait(Wait) == WAIT_TIMEOUT); }