0

作为标题,我在 msdn 或互联网上搜索了一个示例,但我没有找到任何一个 >_<
他们使用 WSAConnect ( S, sa, sa_len , NULL ,NULL ,NULL ,NULL );
我想在接受之前使用这些函数(WSAConnect 和 WSAAccept)来获得一个简单的权限,其中包含 lpCallerData->buf 中的密钥
我已经尝试了来自 msdn 的关于 WSAAccept 的示例用于服务器端以及我关于 WSAConnect 的简单代码,但它总是“lpCallerData == NULL "
抱歉我的英语不好
提前谢谢你的帮助!

我不工作的代码:

服务器端:

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;
}

客户端:

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;
}
4

1 回答 1

1

lpCallerData在您的回调中始终为 NULL,WSAAccept()因为 TCP/IP 不支持在连接建立期间交换调用方/被调用方数据。这在文档中明确说明WSAConnect()

注意Windows 中的 TCP/IP 协议不支持连接数据。仅在 ATM (RAWWAN) 上通过原始套接字支持连接数据。

WSAAccept()文档还指出:

如果没有呼叫者标识或呼叫者数据可用,则相应的参数将为 NULL。许多网络协议不支持连接时调用者数据

...

lpCalleeData->len 最初包含由服务提供者分配并由 lpCalleeData->buf 指向的缓冲区的长度。零值表示不支持将用户数据传回给调用者

话虽如此,即使它受到支持,您也无法WSABUF正确管理结构。您的服务器没有检查 NULL 或len溢出,并且您的客户端代码没有为WSABUF::buf字段分配任何内存。

您的代码需要看起来更像这样:

服务器端:

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;
    }
}

客户端:

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 );

    ...
}
于 2013-04-27T09:42:47.540 回答