Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Multipe Send()';s和Recv()';s正在使用Winsock2_C++_Windows_Sockets_Winsock - Fatal编程技术网

C++ Multipe Send()';s和Recv()';s正在使用Winsock2

C++ Multipe Send()';s和Recv()';s正在使用Winsock2,c++,windows,sockets,winsock,C++,Windows,Sockets,Winsock,我正在使用Winsock2进行一个小型网络项目。我使用的是TCP连接,实际上是以IRC为例,因为IRC相当简单。我所做的是连接到服务器并发送初始缓冲区,以便服务器识别连接。这个很好用 我担心的是我不能再向套接字写入数据。如果在发送初始缓冲区后不使用shutdown()(在SD_SEND上),我的程序似乎会挂起 因此,我要发送的下一个数据(基于RFC 1459)是用户和NICK信息,但是,我觉得使用shutdown()是导致当前问题的原因。有没有办法重新初始化写套接字 谢谢 添加代码 请注意,它们

我正在使用Winsock2进行一个小型网络项目。我使用的是TCP连接,实际上是以IRC为例,因为IRC相当简单。我所做的是连接到服务器并发送初始缓冲区,以便服务器识别连接。这个很好用

我担心的是我不能再向套接字写入数据。如果在发送初始缓冲区后不使用shutdown()(在SD_SEND上),我的程序似乎会挂起

因此,我要发送的下一个数据(基于RFC 1459)是用户和NICK信息,但是,我觉得使用shutdown()是导致当前问题的原因。有没有办法重新初始化写套接字

谢谢

添加代码

请注意,它们位于一个类中,因此它仍然可能会稍微模糊。我正在使用我拥有的元素将其写入一个更简单的示例中。一切都是正确定义的,所以如果我忘记定义东西,我很抱歉,但是我的许多循环变量都是为类的范围定义的

int main(int argc,char *argv[])
{
        int iResult;
        SOCKET Connection;
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if(iResult != 0)
        throw "Startup failed!";

    // Prep stuff
    ZeroMemory(&hints,sizeof(hints)); // This struct is defined addrinfo
    hints.ai_family   = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Now resolve server addr
    iResult = getaddrinfo(argv[1],argv[2],&hints,&result);
    if(iResult != 0)
        throw "getaddrinfo() failed!";

    // Now try to connect
    for(ptr=result;ptr != NULL;ptr = ptr->ai_next)
    {
        Connection = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); // defined in that "hints" struct. argument number 2
        if(Connection == INVALID_SOCKET)
        {
            freeaddrinfo(result);
            WSACleanup();
            throw "Error at socket();";
        }

        // Connect to server
        iResult = connect(Connection, ptr->ai_addr, (int)ptr->ai_addrlen);
        if(iResult != 0)
        {
            closesocket(Connection);
            Connection = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    // Send initial buffer so server know you're there :)
    iResult = send(Connection, "", 1, 0);
    if(iResult == SOCKET_ERROR)
    {
        close();
        throw "Could not send initial buffer!";
    }

    // Close this connection for the inital buffer
    iResult = shutdown(Connection, SD_SEND);
    if(iResult == SOCKET_ERROR)
    {
        close();
        throw "Could not close initial buffer socket!";
    }

        bool connected = true;

        // This is taken from my read function within the class
        // BEGIN READ FUNCTION
    iResult = 0; // Reset
    std::string data = ""; // Capture the output and send it all at once!

    // This only works if we're connected sweet cakes <3
    if(connected)
    {
        do
        {
            iResult = recv(socket, recvbuf, BUFLEN, 0);
            if(iResult > 0)
            {
                // Working properly
                // Save all data even if there is more than BUFLEN sent
                continue;
            }
            else if(iResult == 0)
                // Connection closed properly
                break;
            else
                printf("ERROR!");
        } while(iResult > 0);
    }
    data += recvbuf;
    ZeroMemory(&recvbuf,sizeof(recvbuf));
        // Function returns std::string but essentially this is what happens
        printf("%s",data.c_str());
        // END READ FUNCTION 

        // BEGIN WRITE FUNCTION
    iResult = 0; // Reset
        SOCKET socket = Connection; // Write function arg 1
        char *data; // Write function arg 2

    iResult = send(socket,data,(int)strlen(data),0);
    if(iResult == SOCKET_ERROR)
    {
        close();
        printf("Could not write data: %ld",WSAGetLastError()); 
                return 1;
    }

    // Data sent, let's close the write socket
    iResult = shutdown(socket, SD_SEND);
    if(iResult != 0)
    {
        close();
        printf("Could not close write socket!");
                return 1;
    }

    //return iResult;
        // END WRITE FUNCTION

        // Now that will produce "Could not write data: 0" for any value of data
        // So realistically I want to send the USER and NICK data, then read 
        // and probably process a PING string from the server and send my PONG response

        return 0;
}

因此,它似乎已经超时,因为PING没有及时接收到PONG,但是,我不能在没有首先处理PING请求的情况下发送PONG,这意味着我需要能够在连接关闭之前读取输出。有什么想法吗?

不需要像您这样发送“初始缓冲区”。当客户端连接时,服务器将收到通知,它不依赖于客户端实际发送任何内容。(特别是,IRC协议规定,一旦您连接,服务器将开始向您发送内容。)

shutdown()
的调用非常可疑。你为什么期望这样做?关闭套接字是在连接完成时所做的事情,而不是刚开始时所做的事情。你应该完全删除这个

我不确定什么类型的
recvbuf
,但看起来您使用的不正确。可以附加到
std::string
的东西可能也不能对其调用
ZeroMemory()
,除非其中一个错误。您也没有使用从服务器接收的实际字节数
iResult


您的write函数还包含对
shutdown()
的调用,您应该删除该调用。

不需要像以前那样发送“初始缓冲区”。当客户端连接时,服务器将收到通知,它不依赖于客户端实际发送任何内容。(特别是,IRC协议规定,一旦您连接,服务器将开始向您发送内容。)

shutdown()
的调用非常可疑。你为什么期望这样做?关闭套接字是在连接完成时所做的事情,而不是刚开始时所做的事情。你应该完全删除这个

我不确定什么类型的
recvbuf
,但看起来您使用的不正确。可以附加到
std::string
的东西可能也不能对其调用
ZeroMemory()
,除非其中一个错误。您也没有使用从服务器接收的实际字节数
iResult


您的write函数还包含对
shutdown()
的调用,您应该删除该调用。

我可以推荐一个关于该主题的有趣文档吗?第6章和第7章


它有几个例子。

我可以推荐一个关于这个主题的有趣的文档吗?第6章和第7章

它有几个例子。

根据man send(2)

成功后,这些调用将返回 发送的字符数。关于错误, -返回1,并正确设置errno

发生的情况可能是send不会立即发送完整的缓冲区,您必须在它周围使用一个循环

但这可能不是您的实际问题,因为您正在发送一个空字符串

我强烈建议您使用,以便您可以根据man send(2)检查连接到电线的内容

data += recvbuf;
成功后,这些调用将返回 发送的字符数。关于错误, -返回1,并正确设置errno

发生的情况可能是send不会立即发送完整的缓冲区,您必须在它周围使用一个循环

但这可能不是您的实际问题,因为您正在发送一个空字符串

我强烈建议您使用,这样您就可以检查下到电线的部分

data += recvbuf;
这不行。没有办法知道收到了多少字节。此函数需要C样式的字符串,而不是任意字节块

但你也有一个非常基本的设计问题。您希望您的程序使用IRC协议,但它不包含该协议的任何实现。例如,IRC协议指定了一种特定的消息分隔方式,您没有任何代码来解析这些消息

因此,从读到写的转换基本上是在一个随机的时间发生的,这个时间由TCP定时的反复无常以及服务器如何选择对其输出进行分段决定。由于服务器可以随心所欲地对其输出进行分段(协议明确规定,客户端不能依赖分段来解析协议,而必须依赖面向行的特性),因此程序的行为是不可预测的

这不行。没有办法知道收到了多少字节。此函数需要C样式的字符串,而不是任意字节块

但你也有一个非常基本的设计问题。您希望您的程序使用IRC协议,但它不包含该协议的任何实现。例如,IRC协议指定了一种特定的消息分隔方式,您没有任何代码来解析这些消息