2011-04-19 14 views
6

मुझे टीसीपी आईओसीपी क्लाइंट को लागू करने में कुछ परेशानी हो रही है। मैंने मैक ओएसएक्स पर क्यूक्यू लागू किया है, इसलिए विंडोज़ पर कुछ ऐसा करने की तलाश में था और मेरी समझ यह है कि आईओसीपी निकटतम चीज है। मुख्य समस्या यह है कि GetCompetetionStatus कभी वापस नहीं आ रहा है और हमेशा टाइमआउट आउट हो रहा है। मुझे लगता है कि मॉनिटर करने के लिए हैंडल बनाते समय मुझे कुछ याद आ रहा है, लेकिन यह सुनिश्चित नहीं है कि क्या। यह वह जगह है जहां मैं अब तक मिल गया है:आईओसीपी सी ++ टीसीपी क्लाइंट

मेरे कनेक्ट दिनचर्या: (स्पष्टता के लिए से निपटने के कुछ त्रुटि को दूर)

struct sockaddr_in server; 
struct hostent *hp; 
SOCKET sckfd; 
WSADATA wsaData; 

int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 


if ((hp = gethostbyname(host)) == NULL) 
    return NULL; 
WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED) 
if ((sckfd = WSASocket(AF_INET,SOCK_STREAM,0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) 
{ 
    printf("Error at socket(): Socket\n"); 
    WSACleanup(); 
    return NULL; 
} 

server.sin_family = AF_INET; 
server.sin_port = htons(port); 
server.sin_addr = *((struct in_addr *)hp->h_addr); 
memset(&(server.sin_zero), 0, 8); 

//non zero means non blocking. 0 is blocking. 
u_long iMode = -1; 
iResult = ioctlsocket(sckfd, FIONBIO, &iMode); 
if (iResult != NO_ERROR) 
    printf("ioctlsocket failed with error: %ld\n", iResult); 


HANDLE hNewIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, ulKey, 0); 
CreateIoCompletionPort((HANDLE)sckfd, hNewIOCP , ulKey, 0); 

connect(sckfd, (struct sockaddr *)&server, sizeof(struct sockaddr)); 

//WSAConnect(sckfd, (struct sockaddr *)&server, sizeof(struct sockaddr),NULL,NULL,NULL,NULL); 

return sckfd; 

यहाँ भेजने दिनचर्या है:

(भी स्पष्टता के लिए से निपटने के कुछ त्रुटि निकालने के लिए)
IOPortConnect(int ServerSocket,int timeout,string& data){ 

char buf[BUFSIZE]; 
strcpy(buf,data.c_str()); 
WSABUF buffer = { BUFSIZE,buf }; 
DWORD bytes_recvd; 
int r; 
ULONG_PTR ulKey = 0; 
OVERLAPPED overlapped; 
OVERLAPPED* pov = NULL; 
HANDLE port; 

HANDLE hNewIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, ulKey, 0); 
CreateIoCompletionPort((HANDLE)ServerSocket, hNewIOCP , ulKey, 0); 


BOOL get = GetQueuedCompletionStatus(hNewIOCP,&bytes_recvd,&ulKey,&pov,timeout*1000); 

if(!get) 
    printf("waiton server failed. Error: %d\n",WSAGetLastError()); 
if(!pov) 
    printf("waiton server failed. Error: %d\n",WSAGetLastError()); 

port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (u_long)0, 0); 

SecureZeroMemory((PVOID) & overlapped, sizeof (WSAOVERLAPPED)); 

r = WSASend(ServerSocket, &buffer, 1, &bytes_recvd, NULL, &overlapped, NULL); 
printf("WSA returned: %d WSALastError: %d\n",r,WSAGetLastError()); 
if(r != 0) 
{ 
    printf("WSASend failed %d\n",GetLastError()); 
    printf("Bytes transfered: %d\n",bytes_recvd); 
} 
if (WSAGetLastError() == WSA_IO_PENDING) 
    printf("we are async.\n"); 
CreateIoCompletionPort(port, &overlapped.hEvent,ulKey, 0); 

BOOL test = GetQueuedCompletionStatus(port,&bytes_recvd,&ulKey,&pov,timeout*1000); 

CloseHandle(port); 
return true; 

}

किसी भी अंतर्दृष्टि की सराहना की जाएगी।

+0

क्या आप वास्तव में 'CreateIoCompletionPort' से वापसी मूल्य की जांच करते हैं? –

+0

प्रत्येक फ़ंक्शन में CreateIoCompletionPort दोनों के बाद GetLastError डालने में त्रुटि 87 (गलत पैरामीटर) और त्रुटि 6 (अमान्य हैंडल) देता है। मुझे यकीन नहीं है कि वे गलत क्यों लौट रहे हैं क्योंकि वे दोनों वैध हैंडल (सर्वरसेट और पोर्ट) हैं। – daltoniam

उत्तर

5

आप एक ही सॉकेट को एकाधिक IOCompletionPorts से जोड़ रहे हैं। मुझे यकीन है कि मान्य नहीं है। अपने IOPORTConnect फ़ंक्शन (जहां आप लिखते हैं) में आप CreateIOCompletionPort को एक शॉट हैंडल में 4 बार गुजरते हैं।

मेरी सलाह:

  • एक भी IOCompletion पोर्ट (कि, अंततः, आप कई सॉकेट के साथ संबद्ध है)।
  • कार्यकर्ता धागे का एक पूल बनाएं (CreateThread को कॉल करके) जो प्रत्येक एक लूप में GetQueuedCompletionStatus को कॉल करके IOCompletionPort हैंडल पर अवरुद्ध करता है।
  • एक या अधिक WSA_OVERLAPPED सॉकेट बनाएं, और IOCompletionPort के साथ प्रत्येक को संबद्ध करें।
  • डब्लूएसए सॉकेट फ़ंक्शंस का उपयोग करें जो ओवरलैप्ड ऑपरेशंस को ट्रिगर करने के लिए ओवरराप्पेड * लेते हैं।
  • जारी किए गए अनुरोधों को पूरा करने की प्रक्रिया करें क्योंकि कार्यकर्ता धागे GetQueuedCompletionStatus से वापस आते हैं * आप ऑपरेशन शुरू करने के लिए पास हुए हैं।

नोट: WSASend दोनों 0 देता है, और WSAGetLastError साथ SOCKET_ERROR() WSA_IO_PENDING कोड इंगित करने के लिए के रूप में है कि आप एक आईओ समापन पैकेट GetQueuedCompletionStatus पर पहुंचने से मिल जाएगा के रूप में। कोई अन्य त्रुटि कोड का मतलब है कि आपको तुरंत त्रुटि को संसाधित करना चाहिए क्योंकि आईओ ऑपरेशन कतारबद्ध नहीं था इसलिए आगे कोई कॉलबैक नहीं होगा।

नोट 2: ओवरप्लेड * डब्लूएसएएसएंड (या जो कुछ भी) फ़ंक्शन को पास किया गया है * ओवरक्लेप्ड * GetQueuedCompletionStatus से लौटाया गया है।

struct MYOVERLAPPED { 
    OVERLAPPED ovl; 
}; 
MYOVERLAPPED ctx; 
WSASend(...,&ctx.ovl); 
... 
OVERLAPPED* pov; 
if(GetQueuedCompletionStatus(...,&pov,...)){ 
    MYOVERLAPPED* pCtx = (MYOVERLAPPED*)pov; 
+0

धन्यवाद।मैं इसे लागू करूंगा और देख सकता हूं कि मैं काम कर रहा हूं या नहीं। आपके समय के लिए धन्यवाद। – daltoniam

2

क्रिस मुद्दों के सबसे के साथ पेश किया है और आप शायद पहले से ही उदाहरण कोड के बहुत देखा है, लेकिन ...

: आप कॉल के साथ अधिक संदर्भ जानकारी पारित करने के लिए इस तथ्य का उपयोग कर सकते हैं मेरे पास कुछ मुफ्त आईओसीपी कोड है जो यहां उपलब्ध है: http://www.serverframework.com/products---the-free-framework.html

उस पृष्ठ से जुड़े विषय पर मेरे कई कोडप्रोजेक्ट लेख भी हैं।

+0

लिंक के लिए धन्यवाद मैं एक नज़र डालेगा। – daltoniam