简体   繁体   English

Java-> C ++ TCP套接字直到关闭才发送

[英]Java -> C++ TCP Socket does not send until close

I am facing another TCP Socket issue. 我面临另一个TCP套接字问题。 I've read through a huge bunch of questions an answers to similar issues, but my problem is somehow different. 我已经阅读了很多问题,并回答了类似问题,但是我的问题有所不同。

I have a Java Client and C++ Server. 我有一个Java客户端和C ++服务器。 Everything goes as expected until I'm using different machines (equal to other issues so far) The messages from the client seem to getting stuck in den TCP Buffer. 一切都按预期进行,直到我使用不同的机器为止(到目前为止,它还等同于其他问题)来自客户端的消息似乎卡在了TCP缓冲区中。 When I finally close the socket, everything is sent to the server. 当我最后关闭套接字时,所有内容都发送到了服务器。 But these single messages are controlmessages so I need them to be send immediatly. 但是这些单个消息是控制消息,因此我需要立即发送它们。 As far as I read this is expected behavior, but how do I send reliable control messages. 据我所知,这是预期的行为,但是如何发送可靠的控制消息。

Is there a way to force the messages to be sent. 有没有一种方法可以强制发送消息。 (I can leave the socket open for a couple of minutes with nothing is sent.) (我可以将套接字打开几分钟,不发送任何消息。)

Is there something wrong? 有什么不对? (see the following code) (请参见以下代码)

Do I have to close the socket each time to perform a REAL flush? 每次执行一次真正的冲洗时,我都必须关闭插座吗?

Should I use UDP instead, with an additional amount of protocol work? 我应该使用UDP协议,还是需要额外的协议工作量?

Javacode: Javacode:

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

C++ Code: C ++代码:

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

If you want more of it. 如果您想要更多。 Write it. 写下来。 I left almost everything out. 我几乎遗漏了一切。 ^^ I dont think its relevant. ^^我认为它不相关。 The Communication wents great usually.. No errors at all. 通常,通讯进行得很好。 So its just this TCPBuffer thingi. 所以这只是这个TCPBuffer事情。

I know there should be some delimiter or message length stuff. 我知道应该有一些定界符或消息长度的东西。 But in fact: A message length, which is not sent, does not help. 但实际上:未发送的消息长度没有帮助。 ^^ ^^

Thanks for your help. 谢谢你的帮助。

EDIT #01 The whole bunch of code: 编辑#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;
}

You wanted it.... 你想要...

EDIT #2 Give it one more try 编辑#2再试一次

There are few more things I tried out. 我尝试了几件事。 At first: This problem does not occure on a device connected over real network everytime. 首先:每次通过真实网络连接的设备上都不会发生此问题。 -> Full Reboot Client&Server -> Problem does not occure -> Full Reboot Client&Server -> Problem occures ->完全重新启动客户端和服务器->不会出现问题->完全重新启动客户端和服务器->出现问题

Sadly, I don't know what to take from this habit. 可悲的是,我不知道该养成什么样。

Another thing I stumbled over is the bind and listen socket (in Code SOCKET s). 我偶然发现的另一件事是bind和listen套接字(在Code SOCKET中)。 This socket listens for connections and if the working thread needs a new connection (on startup or if the previous closes) the socket s gives the next queued connection to mConnectedSocket for recv, other connections are backlogged while one is processed. 该套接字侦听连接,并且如果工作线程需要一个新的连接(启动时或前一个关闭),则套接字s将下一个排队的连接提供给mConnectedSocket进行接收,其他连接将在处理一个时积压。 From the Java view: a Socket is connected (Device A). 从Java视图:连接了一个套接字(设备A)。 next socket (Device B) tries to connect. 下一个套接字(设备B)尝试连接。 -> Connection success (its properly controlled in code if this is happens indeed) -> followed by sending data in natural matter. ->连接成功(如果确实发生,则可以通过代码正确控制)->然后以自然状态发送数据。 (The socket is still in the backlog on c++ side) (套接字仍在c ++方面的积压中)

Well, this is hard to transform to the habit I experienced. 好吧,这很难转化为我所经历的习惯。 I'll try to express my thoughts. 我会尽力表达自己的想法。 Javaside: PrintWriter is created. Javaside:PrintWriter已创建。 Feeded with data and is flushed. 馈入数据并被刷新。 Because the connection is not fully established (No additional connectedSocket on C++ side). 因为未完全建立连接(C ++侧没有其他的connectedSocket)。 The flush doesn't work. 冲洗不起作用。 And onClose the socket finally flushes its content. 并且onClose套接字最终刷新其内容。

Please tell me to shut up, if you think so. 如果您认为这样,请告诉我闭嘴。 I dont really know what the "Connection is backlogged" ACTUALLY mean in implementation" ^^ 我真的不知道“连接积压”在实现中实际上是什么意思。

I know, I should open a new thread for each connection, but I can't at the moment. 我知道,我应该为每个连接打开一个新线程,但目前无法。 So stick with this server code. 因此,请坚持使用此服务器代码。

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

PrintWriter.flush();

Or use a writer with automatic flushing. 或者使用带有自动冲洗功能的写入器。

You should also make sure that the server reads a line (until \\n) and not the full 1024 chars, but I don't know what recv() does so I don't know about that. 您还应该确保服务器读取一行(直到\\ n),而不是整个1024个字符,但是我不知道recv()的作用,所以我也不知道。

Fixed it. 修复。 Kind of embarassing... The backlog, i noticed in my edit was indeed the problem. 有点尴尬...我在编辑中发现积压的确是问题所在。 If two at clients at a time connect to the server, the second is backlogged and his messages would be processed, when the first disconnects. 如果同时有两个客户端连接到服务器,则第二个客户端将被积压,并且当第一个客户端断开连接时,将处理他的消息。

Additionally (here comes the clue) 另外(线索来了)

As mentioned before its an android java client. 如前所述,它是一个android java客户端。 There is another thread on java side to receive data from the C++ server. 在Java端还有另一个线程可以从C ++服务器接收数据。 This socket connects on another port. 此套接字连接到另一个端口。 BUT i set the ports and ip addresses to connect to in a settings activity and there was a bad port for the other socket as default value (same as for the issuesocket, wrong variable taken) So this socket connects first and the issuesocket connects into the backlog. 但是我在设置活动中设置了要连接的端口和ip地址,并且另一个套接字的默认端口有一个错误的端口(与issuescket相同,使用了错误的变量),因此,此套接字先连接,issuescket连接到积压。 This default value is only taken if I enter the settings to set another IPAddress (For example, when I connect to a remote host instead of localhost) 仅当我输入设置以设置另一个IPAddress时,才使用此默认值(例如,当我连接到远程主机而不是localhost时)

Incredible circumstances... i didnt even wrote the settings... 令人难以置信的情况...我什至没有写设置...

WIRESHARK would have fixed this. WIRESHARK将解决此问题。

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

As you are using auto flush and even tried using an explicit flush() : 当您使用自动刷新,甚至尝试使用显式flush()

Could be because you don't open the inputStream. 可能是因为您没有打开inputStream。 Try and do a getInputStream() as well. 尝试也执行getInputStream()

Otherwise, Have you tried: 否则,您是否尝试过:

  1. any diff you don't use connect but just give the parameters directly in the Socket constructor? 您不使用connect而是仅在Socket构造函数中直接提供参数的任何差异?

  2. setTcpNoDelay on the socket (shouldn't cause minutes of delay though!!)? setTcpNoDelay上的setTcpNoDelay (虽然不会造成几分钟的延迟!)?

Actually your problem could be on the receiving end, your recv needs to be in a loop (you can google for examples of this). 实际上,您的问题可能在接收端, recv必须处于循环状态(您可以在Google上搜索此示例)。 There is no guarantee not much each call to recv will get. 不能保证每次调用recv不会得到多少。 If you know you are flushing the data on the Java site, that's probably your problem. 如果您知道要刷新Java站点上的数据,则可能是您的问题。

Your loop is incorrectly coded. 您的循环编码错误。 Every new recv() will overwrite the previous one. 每个新的recv()都会覆盖前一个。 You should advance the offset parameter. 您应该提前offset参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM