Java - > C ++ TCP Socket直到关闭才发送

时间:2012-05-18 20:36:06

标签: java c++ sockets tcp stream

我正面临另一个TCP套接字问题。 我已经通过一大堆问题阅读了类似问题的答案,但我的问题有些不同。

我有一个Java客户端和C ++服务器。一切都按预期进行,直到我使用不同的机器(到目前为止等于其他问题) 来自客户端的消息似乎陷入了TCP缓冲区。当我最终关闭套接字时,所有内容都会发送到服务器。但是这些单个消息是控制消息所以我需要它们立即发送。据我所知,这是预期的行为,但我如何发送可靠的控制消息。

有没有办法强制发送消息。 (我可以将套接字打开几分钟而不发送任何内容。)

有什么问题吗? (见以下代码)

每次都要关闭套接字以执行REAL刷新吗?

我应该使用UDP,还需要额外的协议吗?

Javacode:

mSocketSend = new Socket();
mSocketSend.connect(new InetSocketAddress(mServerIp, mSocketPortSend), mTimeOut);
PrintWriter pw = new PrintWriter(mSocketSend.getOutputStream(), true);
pw.println(data);

C ++代码:

   opening socket...(i leave that)
   char* buffer = new char[1024];
   int rc = recv(mConnectedSocket, buf, 1024, 0);

如果你想要更多。写下来。我几乎把所有东西都丢了。 ^^我不认为它的相关性。沟通通常很好..没有任何错误。所以它只是这个TCPBuffer的东西。

我知道应该有一些分隔符或消息长度的东西。但实际上:未发送的消息长度没有帮助。 ^^

感谢您的帮助。

EDIT#01一大堆代码:

mSocket->createSocketServer(22);
    char* buffer = new char[1024];
 while(true){

        int numberBytes = mSocket->receiveChars(buffer, 1024);

        if (numberBytes > 0){
            uninterestingHandlingFunction(buffer);
        }else{
            mSocket->createSocketServer(22);
        }
    }

bool Socket::createSocketServer(u_short port)
{
    if (mConnectedSocket != INVALID_SOCKET)
    {
        closesocket(mConnectedSocket);
    }

    if (s == INVALID_SOCKET)
    {
        WSADATA wsa;

        if (WSAStartup(MAKEWORD(2,0), &wsa) != 0)
            return 0;

        s = socket(AF_INET, SOCK_STREAM, 0);
        if (s == INVALID_SOCKET)
            return 0;

        SOCKADDR_IN addr;
        memset(&addr, 0, sizeof(SOCKADDR_IN));
        addr.sin_family=AF_INET;
        addr.sin_port=htons(port);
        addr.sin_addr.s_addr=ADDR_ANY;

        if (bind(s, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
        {
            s = INVALID_SOCKET;
        } else if (listen(s, 10) == SOCKET_ERROR)
        {
            s = INVALID_SOCKET;
        }

        if (s == INVALID_SOCKET)
        {
            closesocket(s);
            return 0;
        }
    }
    mConnectedSocket = accept(s, NULL, NULL);

    if (mConnectedSocket == INVALID_SOCKET)
    {
        closesocket(s);
        return 0;
    }
    return 1;
}

int Socket::receiveChars(char* buf, unsigned maxSize)
{
    if (mConnectedSocket == INVALID_SOCKET)
        return -1;

    int rc = recv(mConnectedSocket, buf, maxSize, 0);
    if (rc == SOCKET_ERROR)
    {
        std::cout << "Socket: error " << WSAGetLastError() << std::endl;
    }
    return rc;
}

你想要它......

编辑#2再试一次

我尝试了更多的东西。 首先:每次在真实网络上连接的设备上都不会出现此问题。 - &GT;完全重启客户端和服务器 - &gt;问题没有发生 - &gt;完全重启客户端和服务器 - &gt;出现问题

可悲的是,我不知道该从这个习惯中拿走什么。

我偶然发现的另一件事是bind和listen套接字(在Code SOCKET中)。此套接字侦听连接,如果工作线程需要新连接(在启动时或之前关闭),套接字s将下一个排队连接提供给mConnectedSocket以进行recv,则在处理一个连接时会积压其他连接。 从Java视图:连接Socket(设备A)。下一个套接字(设备B)尝试连接。 - &GT;连接成功(如果确实发生这种情况,则在代码中进行适当控制) - &gt;然后以自然物质发送数据。 (套接字仍在c ++方面的积压中)

嗯,这很难改变我所经历的习惯。我会尽力表达自己的想法。 Javaside:PrintWriter已创建。填充数据并刷新。因为连接没有完全建立(在C ++端没有额外的connectedSocket)。冲洗不起作用。然后onClose,套接字最终刷新其内容。

如果您愿意,请告诉我闭嘴。我真的不知道什么是“连接被积压”实际意味着在实施“^^

我知道,我应该为每个连接打开一个新线程,但我现在不能。所以坚持使用这个服务器代码。

7 个答案:

答案 0 :(得分:2)

您需要执行flush(),将数据推出。

答案 1 :(得分:1)

PrintWriter.flush();

或者使用具有自动刷新功能的作家。

你还应该确保服务器读取一行(直到\ n)而不是完整的1024个字符,但我不知道recv()是做什么的,所以我不知道。

答案 2 :(得分:1)

修正了它。有点尴尬...... 我在编辑中注意到的积压确实是问题所在。 如果两个客户端一次连接到服务器,那么第二个是积压的,并且当第一个断开连接时,将处理他的消息。

另外(这是线索)

如前所述,它是一个android java客户端。 Java端有另一个线程从C ++服务器接收数据。此套接字连接在另一个端口上。 但是我在设置活动中设置要连接的端口和IP地址,并且另一个套接字的端口是默认值(与issuesocket相同,采用了错误的变量) 所以这个套接字首先连接,issuesocket连接到backlog。 仅当我输入设置以设置另一个IPAddress时才会使用此默认值(例如,当我连接到远程主机而不是localhost时)

难以置信的情况......我甚至没有写过设置......

WIRESHARK会解决这个问题。

答案 3 :(得分:0)

PrintWriter pw = new PrintWriter(mSocketSend.getOutputStream(), true);
pw.println(data);
pw.flush();

答案 4 :(得分:0)

当您使用自动刷新时,甚至尝试使用明确的flush()

可能是因为你没有打开inputStream。尝试并执行getInputStream()

否则,您是否尝试过:

  1. 您不使用connect的任何差异,只是直接在Socket构造函数中提供参数?

  2. 套接字上的
  3. setTcpNoDelay(不应该导致延迟几分钟!!)?

答案 5 :(得分:0)

实际上您的问题可能在接收端,您的recv需要处于循环中(您可以通过谷歌搜索此示例)。无法保证每次拨打recv的电话都不会太多。如果您知道正在刷新Java站点上的数据,那可能就是您的问题。

答案 6 :(得分:0)

您的循环编码错误。每个新的recv()都会覆盖前一个。你应该提前偏移参数。