As title, I 've searched in msdn or on internet for an example but I didn't find any one >_<
All case they use WSAConnect ( S, sa, sa_len ,NULL ,NULL ,NULL ,NULL );
I wanna use those function (WSAConnect & WSAAccept) for a simple authority with key in lpCallerData->buf before accept
I 've tried the example about WSAAccept from msdn for server side and my simple code about WSAConnect but It's alway "lpCallerData == NULL"
Sorry about my bad english
Thank you in advance with any help!
My not working code:
Server side:
SOCKET SV_Socket;
struct sockaddr_in SV_Channel;
WORD SV_wVersionRequested;
WSADATA SV_wsaData;
int SV_on = 1;
int CALLBACK ConditionAcceptFunc(
LPWSABUF lpCallerId,
LPWSABUF lpCallerData,
LPQOS pQos,
LPQOS lpGQOS,
LPWSABUF lpCalleeId,
LPWSABUF lpCalleeData,
GROUP FAR * g,
DWORD_PTR dwCallbackData
)
{
//printf( "test1\n" );
//if ( memcmp( lpCallerData->buf ,"quyen194" , lpCallerData->len ) == 0 )
if ( lpCallerData->buf[0] == 'q' )
{
//memcpy( lpCalleeData->buf ,"OK" ,2 );
//lpCalleeData->len = 2;
return CF_ACCEPT;
}
else
{
//printf( "Reject request: \n" );
//printf( "Buf: " );
//printf( lpCallerData->buf );
//printf( "\nLen: %d\n" ,lpCallerData->len );
//memcpy( lpCalleeData->buf ,"NOT" ,3 );
return CF_REJECT;
}
}
void AcceptRequest()
{
struct sockaddr_in saClient;
int iClientSize = sizeof(saClient);
//---- ACCEPT connection ------------------
while(true){
int socketNumb = 0;
if(AcceptRequestFunctionLogOnScreen)
if(AllSuccessLogOnScreen)
printf("%d: Data Transfer Listen Socket Waiting...\n",socketNumb);
//C_Socket = accept(SV_Socket,NULL,NULL); // block for connection request
C_Socket = WSAAccept(SV_Socket, (SOCKADDR*) &saClient, &iClientSize, &ConditionAcceptFunc, NULL);
if(C_Socket == INVALID_SOCKET)
{
if(AcceptRequestFunctionLogOnScreen)
if(AllErrorLogOnScreen)
printf("%d: Data Transfer Listen Socket accept failed with error: %ld\n",socketNumb,WSAGetLastError());
WSACleanup();
}
else{
if(AcceptRequestFunctionLogOnScreen)
if(AllSuccessLogOnScreen)
printf("%d: Request to Data Transfer Listen Socket Accepted...\n",socketNumb);
//Mark that Client Socket is inused
C_Alive = true;
//---- SEND bytes -------------------------------------------
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(DataSending),NULL,NULL,NULL);
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(DataReceiving),NULL,NULL,NULL);
while(C_Alive == true){
Sleep(10000);
}
}
}
while(shutdown(SV_Socket,SD_BOTH)){
Sleep(1000);
}
closesocket(SV_Socket);
WSACleanup();
return;
}
Client side:
void Connect2Server()
{
struct sockaddr_in saClient;
int iClientSize = sizeof(saClient);
LPWSABUF lpCallerData= new(WSABUF);
//WSABUF lpCalleeData;// = new(WSABUF);
lpCallerData->buf[0] = 'q';
lpCallerData->len = 1;
printf( "Source: \n" );
printf( "Buf: " );
printf( lpCallerData->buf );
printf( "\nLen: %d\n" ,lpCallerData->len );
system("pause");
//---- try CONNECT -----------------------------------------
int ReturnValue;
int TryToConnect;
int One_socketNumb = 0;
for(TryToConnect=0;TryToConnect<=10;TryToConnect++)
{
//ReturnValue = connect(C_Socket,(SOCKADDR *)&C_Channel, sizeof(C_Channel));
ReturnValue = WSAConnect( C_Socket ,(SOCKADDR *)&C_Channel ,sizeof(C_Channel) ,lpCallerData ,NULL ,NULL ,NULL );
//printf( "Result: \n" );
//printf( "Buf: " );
//printf( lpCalleeData->buf );
//printf( "Len: %d\n" ,lpCalleeData->len );
if (ReturnValue == SOCKET_ERROR){
if(Connect2ServerFunctionLogOnScreen)
if(AllErrorLogOnScreen){
printf("%d: Connect error %ld",One_socketNumb,WSAGetLastError());
printf("%d: Attempt to connect #%d to ChatP2P Server\n",One_socketNumb,TryToConnect+1);
}
Sleep(1000);
if (TryToConnect == 10)
{
WSACleanup();
return; //Couldn't connect
}
}
else{
break;
}
}
//-----------------------------------------------------------
if(Connect2ServerFunctionLogOnScreen)
if(AllSuccessLogOnScreen)
printf("%d: Connect ServerSOCKET: OK...\n",One_socketNumb);
//Mark that Server Socket is inused
C_Alive = true;
//---Connection OK
if(Connect2ServerFunctionLogOnScreen)
if(AllSuccessLogOnScreen)
printf("\n%d: Connected\n",One_socketNumb);
//---- SEND bytes -------------------------------------------
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(DataSending),NULL,NULL,NULL);
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(DataReceiving),NULL,NULL,NULL);
while(C_Alive == true){
Sleep(10000);
}
//---Close Client Socket----------
shutdown(C_Socket,SD_BOTH);
closesocket(C_Socket);
//-------------------------------------
if(Connect2ServerFunctionLogOnScreen)
if(AllSuccessLogOnScreen)
printf("%d: Disconnected\n",One_socketNumb);
WSACleanup();
return;
}
lpCallerData
is always NULL in your WSAAccept()
callback because TCP/IP does not support exchanging caller/callee data during connection establishment. This is clearly stated in the WSAConnect()
documentation:
Note Connect data is not supported by the TCP/IP protocol in Windows. Connect data is supported only on ATM (RAWWAN) over a raw socket.
The WSAAccept()
documentation also states:
If no caller identification or caller data is available, the corresponding parameters will be NULL. Many network protocols do not support connect-time caller data.
...
The lpCalleeData->len initially contains the length of the buffer allocated by the service provider and pointed to by lpCalleeData->buf. A value of zero means passing user data back to the caller is not supported.
With that said, even if it were supported, you are not managing the WSABUF
structures correctly anyway. Your server is not checking for NULL or len
overflows, and your client code is not allocating any memory for the WSABUF::buf
fields.
Your code would need to look more like this instead:
Server side:
int CALLBACK ConditionAcceptFunc(
LPWSABUF lpCallerId,
LPWSABUF lpCallerData,
LPQOS pQos,
LPQOS lpGQOS,
LPWSABUF lpCalleeId,
LPWSABUF lpCalleeData,
GROUP FAR * g,
DWORD_PTR dwCallbackData
)
{
//printf( "test1\n" );
//if ((lpCallerData) && (lpCallerData->len >= 8) && (memcmp(lpCallerData->buf, "quyen194", 8) == 0))
if ((lpCallerData) && (lpCallerData->len > 0) && (lpCallerData->buf[0] == 'q'))
{
//if ((lpCalleeData) && (lpCalleeData->len > 0)) {
// memcpy( lpCalleeData->buf, "OK", 2 );
// lpCalleeData->len = 2;
//}
return CF_ACCEPT;
}
else
{
//printf( "Reject request: \n" );
//if ((lpCallerData) && (lpCallerData->len > 0)) {
// printf( "Buf: %*s", lpCallerData->len, lpCallerData->buf );
// printf( "\nLen: %d\n", lpCallerData->len );
//}
//if ((lpCalleeData) && (lpCalleeData->len > 0)) {
// memcpy( lpCalleeData->buf, "NOT", 3 );
// lpCalleeData->len = 3;
//}
return CF_REJECT;
}
}
Client side:
void Connect2Server()
{
...
WSABUF CallerData;
WSABUF CalleeData;
char CallerBuf = 'q';
CallerData.buf = &CallerBuf;
CallerData.len = 1;
char CalleeBuf[12] = {0};
CalleeData.buf = CalleeBuf;
CalleeData.len = 12;
printf( "Source: \n" );
printf( "Buf: %*s", CallerData.len, CallerData.buf );
printf( "\nLen: %d\n", CallerData.len );
...
ReturnValue = WSAConnect( C_Socket, (SOCKADDR *)&C_Channel, sizeof(C_Channel), &CallerData, &CalleeData, NULL, NULL );
//printf( "Result: \n" );
//printf( "Buf: %*s", CalleeData.len, CalleeData.buf );
//printf( "Len: %d\n", CalleeData.len );
...
}
来源:https://stackoverflow.com/questions/16247621/how-to-use-wsaconnect-and-wsaaccept-for-sending-receving-init-data-before-accept