首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Winsock2的Multipe ()和Recv()

使用Winsock2的Multipe ()和Recv()
EN

Stack Overflow用户
提问于 2010-07-23 21:31:28
回答 4查看 2.3K关注 0票数 1

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

我担心的是,我不能再次写入套接字。如果在发送初始缓冲区后不使用SD_SEND(),那么我的程序就会挂起。

所以我想要发送的下一个数据(基于RFC 1459)是用户和尼克信息,但是,我觉得使用issue ()是造成我当前问题的原因。有没有重新初始化写套接字的方法?

谢谢!

添加了代码

请注意,它们位于一个类中,所以它可能仍然有些模糊。我正在用我的元素将它写成一个简单的例子。所有的东西都被正确地定义了,所以如果我忘记定义东西,我很抱歉,但是我的许多循环变量都是为类的作用域定义的。

代码语言:javascript
复制
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;
}

我希望这能澄清一切!

编辑

我想我已经弄清楚出了什么问题。我对我的代码做了下面的更正;谢谢各位。然而,这是我的阅读循环,是混乱的事情。即使在获得了所有信息之后,它似乎也在等待连接关闭,然后才发送输出。有什么想法吗?我的输出当前如下所示(写入/总计的字节是我添加的,以确保所有的数据都正常运行)

代码语言:javascript
复制
Bytes Written: 41
Bytes Total: 41
Data: ERROR :Closing Link: raged123[127.0.0.1] 6667 (Ping timeout)
...
:irc.foonet.com NOTICE AUTH :*** Found your hostname (cached)
PING :2ED39CE5
[A bunch of funny characters]WinSock 2.0

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-07-23 22:23:04

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

打给shutdown()的电话非常可疑。你为什么要这么做?关闭套接字是在连接完成时所做的事情,而不是刚开始的时候。你应该把这个完全移除。

我不知道recvbuf是什么类型,但看起来您使用的不正确。可以附加到std::string的东西可能也不能让ZeroMemory()调用它,而不会出现其中一个错误。您还没有使用iResult,这是从服务器接收到的实际字节数。

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

票数 2
EN

Stack Overflow用户

发布于 2010-07-23 22:28:12

我可以建议一份关于这个主题的有趣的文件吗?Beej网络编程指南第6章和第7章

它有几个例子。

票数 3
EN

Stack Overflow用户

发布于 2010-07-23 22:32:17

根据人类发送(2)

成功后,这些调用返回发送的字符数。如果出现错误,则返回-1,并适当设置errno。

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

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

我强烈建议使用Wireshark,这样您就可以检查到底发生了什么

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3322538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档