Socat forking each TCP packet - socat

In order to forward all the TCP packets over port 8000 I'm using socat -d -d tcp-l:8000,pktinfo,keepalive,keepidle=10,keepintvl=10,keepcnt=100,ignoreeof,fork system:'bash ./ServersManagerConnector.sh' with the fork option in order to support multiple connections.
Let's say ServersManagerConnector.sh reads one byte and reply to the socket with the same byte. Then, you connect to the port 8000, send 'a', and you read 'a', no problem so far.
Here's the tricky part: ServersManagerConnector.sh never stops (you can see the code here, where there's a while true). Following the previous example, imagine you send one byte and it replies forever with the same byte. So, you send 'a', you read 'aaaaa...'.
You may expect not to work if you send 'a' and then 'b' (as you're using the same connection, only one fork has been made and it's stuck in the while loop). But I'm reading both 'a' and 'b' from the connection, as if socat is making two forks over the same TCP connection.
Anyone knows if is's something related with the socat params? Thanks.
Edit: by printing the PID I can see it is forking twice the program, and by printing $SOCAT_PEERADDR:$SOCAT_PEERPORT I can see that it is changing the port (but the program that calls the .sh it's just opening one socket).

Related

Read signal level for ppp connection on RasPI

I have a RasPI 3 with SIM800L connected via UART.
I use PPP connection to enable network traffic, and I want to get the signal level via AT command but device is busy when PPP is on.
Is it possibile to access to signal level? Or send a AT commands?
You can suspend your PPP call using +++ escape sequence. Something you need to know about the escape sequence:
It doesn't end the PPP connection; it just makes you control again AT UART while in the background it is mantained active
Before sending it, you must avoid sending characters for 1 second
The +++ string needs to be sent with no further character in the middle within 1 second
After sending it, you must avoid sending characters for 1 second. Only then it will be interpreted as escape sequence (this is to avoid +++ to be misinterpreted as data)
After you receive the OK response, you have AT interface back and you can send AT commands without dropping PPP connection, for example your AT+CSQ command to query signal quality.
Of course it is better to avoid to stay too much in suspension, in order to avoid inactivity timeouts from the remote peer.
After you're done with the commands, you can restore data mode with ATOcommand.

recv function for winsock socket

I have a server application which is connected with telnet client(i.e. telnet localhost _port_num - here port number is same associated with the server application),
My application works correctly, but the thing is I used recv as follows:
#define BUFLEN 512
char buf[BUFLEN];
iResult = recv(sd, (char *)buf, BUFLEN, 0);
here recv call returns as soon as any character pressed over the connected telnet terminal, and most of the time iResult is 1 or some times 2, Even though I wouldn't press enter telnet client sends frame containing a single character to the server application.
How can I make sure that recv should return after BUFLEN read ?
In case of linux recv works as expected, get blocks until enter.
Any help or pointers are greatly appreciated.
Q: How can I make sure that ... BUFLEN read ?
A: You read in a loop until you get all the characters you expect. Or until you get a timeout, or an error.
You need to call recv function again and again until your desired amount of data is received. Please note that when you use TCP Sockets, you cannot make sure if you receive all data in single receive call. If you send data using single TCP Send() call, then it is fairly possible that you receive it in multiple receives as TCP sockets are Stream Sockets.
The recv() function returns the number of bytes received, so you can keep calling the function until you get all they bytes.

Windows socket write() is blocked by a read() unexpectedly

(this is an updated repost of a previously asked question, posted with old account which I've lost the credentials for)
I'm writing a client-server program, where the client is C++/winapi and the server is C#/.net.
socket is an AF_INET/ SOCK_STREAM and I'm using Readfile() and WriteFile() for socket IO at client.
the client have a loop where it reads from server (and may block the calling thread [denote t1] , which is fine with me). it also have another thread [denote t2] , that wait on an Event object with a timeout.
if the timeout is reached (and the Event is yet to be singled) the t2 thread, will write (exacly on byte) on the same socket.
The problem I have, is that it seems like the write won't return untill the read on t1 returns (in some legitimate scnerions it will never happen) , as if the socket was not full-duplex.
I've checked it buttom to top, there are no other thread-related comlications. I acctually ran the client from a diffrent machine, and used wireshark to sniff traffic. After the timeout was reached, there was nothing on the wire (no matter how long I wait) , untill I wrote some data from server side (so the read() on t1 returned) - and just right after that, the write() of client is finally transmitted.
As I explained in your earlier question, sockets are full duplex. A read in one thread will not block a write in another thread, and vice versa.

TCP socket stops receiving data until closed

I have a really weird problem that is driving me crazy.
I have a Ruby server and a Flash client (Action Script 3). It's a multiplayer game.
The problem is that everything is working perfect and then, suddenly, a random player stops receiving data. When the server closes the connection because of inactivity, about 20-60 seconds later, the client receives all the buffered data.
The client uses XMLsocket for retrieving data, so the way the client receives data is not the problem.
socket.addEventListener(Event.CONNECT, connectHandler);
function connectHandler(event)
{
sendData(sess);
}
function sendData(dat)
{
trace("SEND: " + dat);
addDebugData("SEND: " + dat)
if (socket.connected) {
socket.send(dat);
} else {
addDebugData("SOCKET NOT CONNECTED")
}
}
socket.addEventListener(DataEvent.DATA, dataHandler);
function dataHandler(e:DataEvent) {
var data:String = e.data;
workData(data);
}
The server flushes data after every write, so is not a flushing problem:
sock.write(data + DATAEOF)
sock.flush()
DATAEOF is null char, so the client parses the string.
When the server accepts a new socket, it sets sync to true, to autoflush, and TCP_NODELAY to true too:
newsock = serverSocket.accept
newsock.sync = true
newsock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
This is my research:
Info: I was dumping netstat data to a file each second.
When the client stops receiving data, netstat shows that socket status is still ESTABLISHED.
Some seconds after that, send-queue grows accordingly to data sent.
tcpflow shows that packets are sent 2 times.
When the server closes the socket, socket status changes to FIN_WAIT1, as expected. Then, tcpflow shows that all buffered data is sent to the client, but the client don't receives data. some seconds after that, connection dissapears from netstat and tcpflow shows that the same data is sent again, but this time the client receives the data so starts sending data to the server and the server receives it. But it's too late... server has closed connection.
I don't think it's an OS/network problem, because I've changed from a VPS located in Spain to Amazon EC2 located in Ireland and the problem still remains.
I don't think it's a client network problem too, because this occurs dozens of times per day, and the average quantity of online users is about 45-55, with about 400 unique users a day, so the ratio is extremely high.
EDIT:
I've done more research. I've changed the server to C++.
When a client stops sending data, after a while the server receives a "Connection reset by peer" error. In that moment, tcpdump shows me that the client sent a RST packet, this could be because the client closed the connection and the server tried to read, but... why the client closed the connection? I think the answer is that the client is not the one closing the connection, is the kernel. Here is some info: http://scie.nti.st/2008/3/14/amazon-s3-and-connection-reset-by-peer
Basically, as I understand it, Linux kernels 2.6.17+ increased the maximum size of the TCP window/buffer, and this started to cause other gear to wig out, if it couldn’t handle sufficiently large TCP windows. The gear would reset the connection, and we see this as a “Connection reset by peer” message.
I've followed the steps and now it seems that the server is closing connections only when the client losses its connection to internet.
I'm going to add this as an answer so people know a bit mroe about this.
I think the answer is that the kernel is the one closing the connection. Here is some info: http://scie.nti.st/2008/3/14/amazon-s3-and-connection-reset-by-peer
Basically, as I understand it, Linux kernels 2.6.17+ increased the maximum size of the TCP window/buffer, and this started to cause other gear to wig out, if it couldn’t handle sufficiently large TCP windows. The gear would reset the connection, and we see this as a “Connection reset by peer” message.
I've followed the steps and now it seems that the server is closing connections only when the client losses its connection to internet.

Ruby TCPSocket write doesn't work, but puts does?

I'm working on a Ruby TCP client/server app using GServer and TCPSocket. I've run into a problem that I don't understand. My TCPSocket client successfully connects to my GServer, but I can only send data using puts. Calls to TCPSocket.send or TCPSocket.write do nothing. Is there some magic that I'm missing?
tcp_client = TCPSocket.new( ipaddr, port )
tcp_client.puts( 'Z' ) # -> GServer receives "Z\n"
But if I use write or send...
tcp_client = TCPSocket.new( ipaddr, port )
tcp_client.write( 'Z' ) # -> nothing is received
tcp_client.send( 'Z' ) # -> nothing is received
Thanks for the help
Additional information:
The behavior is the same on Linux & Windows.
Flushing the socket after write doesn't change the behavior.
Are you sure the problem isn't on the server side? Are you using some method to read that expects a string or something ending in "\n"?
With buffering taken care of in previous posts to address the question of whether the data is being sent consider capturing the data on the line using something like wireshark. If the data you are sending is seen on the line then the server isn't receiving it.
Otherwise, if the data isn't going onto the line, TCP may hold onto data to avoid sending a single segment with only a few bytes in it (see Nagle's Algorithm). Depending on your OS or TCP vendor you may have different behaviour, but most TCP stacks support the TCP_NODELAY option which may help get the data out in a more timely manner.
tcp_client.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
This can help debugging, but typically shouldn't be left in production code if throughput is higher priority than responsiveness.
Try explicitly flushing:
tcp_client = TCPSocket.new( ipaddr, port )
tcp_client.write( 'Z' )
tcp_client.send( 'Z' )
tcp_client.flush
This way, the output is buffered at most only until the point at which you decide it should be sent out.
Hi there the reason should be related to the fact puts add automatic LF and CRL to your string.
If you want to use send or write you need to add them yourself so for instance that would be:
tcp_client.send( "Z\r\n",0)
I had the same problem, so after reading the socket, I had to explicitly delete the last instance of "\n" by doing the following:
client_socket.gets.gsub(/\n$/, '')

Resources