【发布时间】:2012-05-26 10:12:29
【问题描述】:
我面临另一个 TCP 套接字问题。 我已经阅读了大量问题以及类似问题的答案,但我的问题在某种程度上有所不同。
我有一个 Java 客户端和 C++ 服务器。一切都按预期进行,直到我使用不同的机器(到目前为止等于其他问题) 来自客户端的消息似乎卡在了 den TCP 缓冲区中。当我最终关闭套接字时,所有内容都发送到服务器。但是这些单条消息是控制消息,所以我需要立即发送它们。据我所知,这是预期的行为,但我如何发送可靠的控制消息。
有没有办法强制发送消息。 (我可以让套接字打开几分钟而不发送任何内容。)
有什么问题吗? (见以下代码)
是否每次都必须关闭套接字才能执行真正的刷新?
我是否应该使用 UDP 来替代协议工作量?
Java代码:
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 再试一次
我尝试了更多的东西。 起初:这个问题不会每次都在通过真实网络连接的设备上发生。 -> 完全重启客户端和服务器 -> 问题没有发生 -> 完全重启客户端和服务器 -> 问题发生
可悲的是,我不知道如何从这个习惯中吸取教训。
我偶然发现的另一件事是绑定和侦听套接字(在 Code SOCKET 中)。此套接字侦听连接,如果工作线程需要一个新连接(在启动时或先前关闭时),套接字 s 将下一个排队的连接提供给 mConnectedSocket 以进行接收,其他连接在处理一个连接时会积压。 从 Java 视图:连接了一个 Socket(设备 A)。下一个套接字(设备 B)尝试连接。 -> 连接成功(如果确实发生,则在代码中正确控制)-> 随后以自然方式发送数据。 (socket在c++端还在积压中)
嗯,这很难转变为我所经历的习惯。我会尽量表达我的想法。 Javaside:创建 PrintWriter。输入数据并刷新。因为连接没有完全建立(C++端没有额外的connectedSocket)。冲洗不起作用。并且 onClose 套接字最终刷新了它的内容。
如果你这么认为,请告诉我闭嘴。我真的不知道“连接积压”在实施中的实际含义”^^
我知道,我应该为每个连接打开一个新线程,但我现在不能。所以坚持使用这个服务器代码。
【问题讨论】:
-
你试过
pw.flush()吗? -
PrintWriter(OutputStream, boolean autoflush) 应该在 '\n' 上完成工作,但是是的.. 我也试过了
-
buf = 缓冲区?服务器等待 1024 字节或 eof?
-
哦该死的。是的,一起复制的。缓冲区分配在其他地方,并作为 buf 传递给 receiveFunc。第二个问题是我真的不知道的事情。我目前的期望是当接收到至少一个字节时,recv 返回。
-
是的,它也确实返回了 C++ 中的可用字节。
标签: java c++ sockets tcp stream