I'm having an issue making a TCP Server using Spring-Integration.
I've set my server up to accept TCP Connections from a black box client. The client will connect to the server and start periodically sending it string data.
What I'm seeing is after the connection is established (I get confirmation from the client side) I don't receive a print statement on the server until about 30 seconds have passed, where I get 5 messages all at once.
I've monitored incoming data over wireshark and the client is sending data at regular intervals, but the server doesn't read from the incomingStream frequently enough. Is there a way to configure the TcpServer that it reads data from incoming clients more frequently?
fun flow() = IntegrationFlows.from(
Tcp.inboundAdapter(Tcp.nioServer(port).serializer(ByteArrayRawSerializer()).deserializer(ByteArrayRawSerializer()))
.errorChannel(errorChannel())
)
.transform(ObjectToStringTransformer())
.handle { payload: String, headers: MessageHeaders ->
println(payload)
}
.get()
The ByteArrayRawSerializer uses the socket close to detect the end of a message.
TCP is a streaming protocol and, if you want to send multiple messages over the socket, you need to delimit the data somehow so the server can determine when one message ends and the next one starts. See the documentation.
TCP is a streaming protocol. This means that some structure has to be provided to data transported over TCP so that the receiver can demarcate the data into discrete messages. Connection factories are configured to use serializers and deserializers to convert between the message payload and the bits that are sent over TCP. This is accomplished by providing a deserializer and a serializer for inbound and outbound messages, respectively. Spring Integration provides a number of standard serializers and deserializers.
...
The ByteArrayRawSerializer, converts a byte array to a stream of bytes and adds no additional message demarcation data. With this serializer (and deserializer), the end of a message is indicated by the client closing the socket in an orderly fashion. When using this serializer, message reception hangs until the client closes the socket or a timeout occurs.
My guess is the client is not closing the connection after sending the message and there is a 30 second SO timeout (either on the client or server - you don't show your connection factory configuration).
Related
I have a server process running that listens on a port. I can establish the connection with this port, but when I try to send data, the client reports that data has been sent, while the server never receives it.
I am using WireShark to trace the data, and I can't find the data packet I sent, which means it was never received. So here's my question. Does this mean that:
The packet has never reached the network adapter on the server side?
or,
The server process never called the receiving API (recv() or equivalent)?
In other words, are TCP packets transmitted only when the receiving side calls the receiving API, or are they transmitted automatically whenever they are sent, and the receiving API only reads the buffered data?
I'm looking at a proto file which has a bidirectional stream between the client and the server. Does this mean that the client and server can send and receive messages arbitrarily? I'm more confused about the server side. How can the server send data over this bidirectional stream arbitrarily? What would be the trigger?
Thanks!
From the docs:
In a bidirectional streaming RPC, again the call is initiated by the
client calling the method and the server receiving the client
metadata, method name, and deadline. Again the server can choose to
send back its initial metadata or wait for the client to start sending
requests.
What happens next depends on the application, as the client and server
can read and write in any order - the streams operate completely
independently. [...]
This means: the client would establish the connection to the server and you'd then have a connection on wich both parties can read/write.
My program is similar to a HTTP proxy, it waits for messages on an interface and it forwards them to another interface. The application uses only IOCP, both client and server sides. Sometimes, the client is slower (in a ratio of 10 or 100) than the server, which can not buffering too much data.
How can I suspend an established TCP connection then resume it without losing any message? I tried to delay the post of a new recv IOCP event, but some messages are lost.
C++/Windows 7+
I tried to delay the post of a new recv IOCP event
That should in fact do the trick. Your server side TCP connection's receive buffer would then fill up to the receive buffer size as set on your socket, at which point the socket will push back to the sending side of that socket, which - by standard means of TCP flow control - simply stops sending more packets until the receiver signals having processed more messages.
Now it depends on the sending side how long it wants to wait (timeout), before disconnecting.
"some messages are lost"
That can only happen with TCP if you get disconnected, which both the sender and the receiver will take notice of. So data isn't simply lost. It depends on your network protocol on top of TCP though whether the sender application can know how much of the messages the receiving application (your proxy, in this case) successfully processed.
There are two techniques for implementing Comet. One uses HTTP streaming, which uses a single persisted TCP connection to send and receive multiple HTTP requests/responses between client/server.The second is HTTP long polling, which keeps a connection open by the server, and, as soon as an event occurs, the response is committed and the connection is closed. Then, a new long-polling connection is reopened immediately by the client waiting for new events to arrive.
I am using the Faye ruby gem and I noticed it uses Comet/Bayeux out of the box. But I cannot find out which type of Comet technique it uses. I just gather that Bayeux is publish-subscribe protocol. I'm curious to know if it suffers the same shortcomings of HTTP streaming and long polling. Does it allow full-duplex communication (communication in both directions, and, unlike half-duplex, allows this to happen simultaneously.)?
Your definition of HTTP streaming and long-polling are not correct.
In HTTP streaming, the client sends a request to the server, and the server replies with an "infinite" response that contains small chunks of data (messages), typically using the chunked transfer encoding.
This mechanism has been standardized as EventSource (a.k.a Server-Sent Events).
It is a server-to-client only push of events.
For the client to send another message to the server, it has to open a new connection.
In HTTP long-polling, the client sends a request that is held by the server until an event (or a timeout) occurs, then the response is committed but the connection is not closed.
The connection is kept open and other requests may be sent on that connection, both normal or long-polling requests (one at a time, of course).
The Bayeux protocol is an application protocol on top of a transport protocol such as HTTP or WebSocket.
HTTP is a full duplex protocol in the context of a single request/response exchange. Multiple HTTP exchanges are serialized (that is, executed one after the other). The HTTP request/response exchange is the unit of serialization.
WebSocket is a full duplex protocol in the context of WebSocket messages. WebSocket messages may be sent and received simultaneously. The WebSocket message is the unit of serialization.
Bayeux inherits the characteristics of the transport protocol is it carried on. The Bayeux protocol itself does not itself have any "duplexness" characteristics, you can think of it just as a way to format messages in a particular textual form.
Both CometD and Faye use Bayeux over both WebSocket and HTTP long-polling.
I developed a chat server using websocket in cowboy, but I want to know if the message sent by server to client success.How can I know?
Websocket is a rather thin abstraction layer on top of a conventional TCP socket. After the initial handshake the difference is minimal. So, the question is: how do I know if a data chunk was received by the remote peer? The short answer: only if the peer acknowledges it explicitly by the means of application-level protocol. Remote client will send TCP ACK packets for every data packet you will send it, but this fact is well hidden from the application for good reasons. Receiving ACK packet only means that remote TCP stack has dealt with it, but says nothing about how (and if) the client application has processed it.
Add a special "acknowledge receive" message type to your chat protocol. Include a monotonically increasing sequence number in all of your outgoing messages, and include the SN of the received message in the ACK message to know exactly how much data the client has already processed.