Does gen_tcp:recv/3 closes the socket if the timeout is reached? - sockets

I currently have a server that handles multiple connections from clients, and client that connects to the server using two connections. My client has two processes that handle respectively sending and receiving to and from the server, but not both. The problem I currently have is when I want to close the socket, my reading process is stuck on the gen_tcp:recv/2 block. If I put a timeout, the socket is closed when the timeout has been reached. My question is, is it possible to have gen_tcp:recv/3 call that doesn't closes the socket.
This is how my reading process looks like.
read(Socket, Control) ->
Control ! ok,
receive
read ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
%% handling for messages;
Other ->
io:format(Other)
end,
read(self()), %% this sends "read" to itself with "!"
read(Socket, Control);
{error, Reason} ->
io:format(Reason)
end;
close ->
io:format("Closing Reading Socket.~n"),
gen_tcp:close(Socket)
end.
As you can see here, the process will never be able to receive a close if recv/2 doesn't read anything.

Sure, gen_tcp:recv/3 with timeout set to infinity will not close the socket :) See the official documentation.
Edit:
From the documentation:
This function receives a packet from a socket in passive mode.
Check the documentation for setopts/2 to understand the difference between passive and active modes. In particular:
If the value is false (passive mode), the process must explicitly receive incoming data by calling gen_tcp:recv/2,3.
Your process can only do one thing at a time - either listen for the close message from another process or wait for the TCP packet. You could try to use the gen_tcp:controlling_process/2 but I don't know the details. Another solution would be to handle the recv/3 in a separate (third) linked process and kill the process when the close is received.
The better way would be to use an active socket instead, see the Examples section in the official documentation for some guide how to do that.
The best way in my opinion would be to use the OTP gen_server to handle both, the close message and incoming TCP packets in the same process. There is an excellent tutorial in the Erlang and OTP in Action book on how to implement that and here is the code example on Github.

Related

Is it OK to shutdown socket after write all data to it?

I'm writing simple http server.
I want to shutdown socket after server send all data.
I considered that compare return byte of write() to socket with actuall content length, but I had read that the return value just means that data moved to send-buffer of the socket. (Im not sure and I don't know how can I check it)
If so, can I shutdown the socket just after check the bytes are same? What if the datas sended need to be retransmitted at TCP level after server send FIN flag?
The OS does not discard data you have written when you call shutdown(SHUT_WR). If the other end already shut down its end (you can tell because you received 0 bytes) then you should be able to close the socket, and the OS will keep it open until it has finished sending everything.
The FIN is treated like part of the data. It has to be retransmitted if the other end doesn't receive it, and it doesn't get processed until everything before it has been received. This is called "graceful shutdown" or "graceful close". This is unlike RST, which signals that the connection should be aborted immediately.

Epoll events for connecting sockets

I create epoll and register some non-blocking sockets which try connect to closed ports on localhost. Why epoll tells me, that i can write to this socket (it give event for one of created socket with eventmask contain EPOLLOUT)? But this socket doesn't open and if i try send something to it i get an error Connection refused.
Another question - what does mean even EPOLLHUP? I thought that this is event for refused connection. But how in this case event can have simultaneously EPOLLHUP and EPOLLOUT events?
Sample code on Python:
import socket
import select
poll = select.epoll()
fd_to_sock = {}
for i in range(1, 3):
s = socket.socket()
s.setblocking(0)
s.connect_ex(('localhost', i))
poll.register(s, select.EPOLLOUT)
fd_to_sock[s.fileno()] = s
print(poll.poll(0.1))
# prints '[(4, 28), (5, 28)]'
All that poll guarantees is that your application won't block after calling corresponding function. So you are getting what you've paid for - you can now rest assured writing to this socket won't block - and it didn't block, did it?
Poll never guarantees that corresponding operation will succeed.
poll/select/epoll return when the file descriptor is "ready" but that just means that the operation will not block (not that you will necessarily be able to write to it successfully).
Likewise for EPOLLIN: for example, it will return ready when a socket is closed; in that case, you won't actually be able to read data from it.
EPOLLHUP means that there was a "hang up" on the connection. That would really only occur once you actually had a connection. Also, the documentation (http://linux.die.net/man/2/epoll_ctl) says that you don't need to include it anyway:
EPOLLHUP
Hang up happened on the associated file descriptor. epoll_wait(2) will always wait for this event; it is not necessary to set it in events.

Erlang: When does a process terminate and how does gen_tcp:controlling_process(Socket, Pid) work?

What I want to know is whether a process Pid gets terminated when the socket closes if the controlling process is created using gen_tcp:controlling_process(Socket, Pid), and also under what conditions does the socket send this message {tcp_closed, Socket}? Is there a way to prevent the socket on the server side from closing, or is that always normal? Also is there any specific way to terminate a process knowing the Pid?
gen_tcp:controlling_process(Socket, Pid) is used to give the control of a Socket to the process Pid. It implies nothing about the behavior of this process when the Socket is closed.
There are to cases to consider:
You open the server Socket in the mode {active,false} in this case the server will know that the Socket is closed when it calls the function gen_tcp:recv(Sock, Len) getting the answer {error, closed} instead of the expected {ok, Binary}. I recommend you to use this mode if you intend to use gen_tcp:controlling_process(Socket, Pid) because it allow you to avoid a race condition in your code.
You open the server Socket in the mode {active,true} or {active,once}, in this case, the server will receive a message {tcp_closed, Socket}. In this case, there is a race condition see topic Erlang: Avoiding race condition with gen_tcp:controlling_process
I don't think it is the role of the server to prevent any Socket to close, but rather to always be ready to accept a connection.
Last it is always possible to terminate a process, using your own protocol for a smooth end for example Pid ! {stop,Reason} or a more brutal way using exit(Pid, Reason).

socket program setup

I am writing my first socket program to connect to my host to server running on other PC.
I am referring following link but did not got what is the meaning of this line.
http://www.thegeekstuff.com/2011/12/c-socket-programming/
The call to the function ‘listen()’ with second argument as ’10′
specifies maximum number of client connections that server will queue
for this listening socket.
Means to say that it will listen 10 times to new connection request. what actually happen at listen :?:
We will enter while loop once some client connect onto the socket right And inside while loop does accept blocks if no client is requesting to connect to socket on second loop of while :?:
When we are inside while loop does listen() system call is still working or terminates :?:
Also when we will get out of while loop :?:
Please can someone on forum can help me to understand this.
What the listen call does is tell the system the size of the queue it should use for new connections. This queue is only used for connections you have not accepted yet, so it's not the number of total connections you will have.
Besides setting the size of the incoming-connections queue, it also sets a flag on the socket that says it's a passive listening socket.
The stuff that listen does is set on the socket, so as long as the socket is open the queue and the flag is valid.

erlang sockets and gen_server - no data received on server side

In a nutshell:
I am trying to make a socket server to which clients connect and send/receive messages (based on the sockserv code in Learn you some erlang tutorial http://learnyousomeerlang.com/buckets-of-sockets)
Server side components:
supervisor - unique, started at the very beginning, spawns processes with gen_server behaviour
gen_server behaviour processes - each one deals with a connection.
Client side:
client which connects to the socket and sends a few bytes of data and then disconnects.
Code details
My code is pretty much the same as in the presented tutorial. The supervisor is identical. The gen_server component is simplified so that it has only one handle_info case which is supposed to catch everything and just print it.
Problem
The connection succeeds, but when the client sends data, the server behaves as though no data is received (I am expecting that handle_info is called when that happens).
handle_info does get called but only when the client disconnects and this event is reported with a message.
My attempts
I have played around with different clients written in Erlang or Java, I have tried setting the active/passive state of the socket. The author of the tutorial sets {active, once} after sending a message. I ended up just setting {active, true} after the AcceptSocket is created as such: (the gen_server proc is initialized with a state which contains the original ListenSocket created by the supervisor)
handle_cast(accept, S = #state{socket=ListenSocket}) ->
{ok, AcceptSocket} = gen_tcp:accept(ListenSocket),
io:format("accepted connection ~n", []),
sockserv_sup:start_socket(), % a new acceptor is born, praise the lord
inet:setopts(AcceptSocket, [{active, true}]),
send(AcceptSocket, "Yellow", []),
{noreply, S#state{socket=AcceptSocket, next=name}}.
send(Socket, Str, Args) ->
ok = gen_tcp:send(Socket, io_lib:format(Str++"~n", Args)),
ok.
handle_info(E, S) ->
io:format("mothereffing unexpected: ~p~n", [E]),
{noreply, S}.
It has aboslutely no effect. handle_info only gets called when the connection is lost because the client disconnects. whenever the client sends data nothing happens.
What could be the problem? I have spend quite some time on this, I really have no idea.
Many thanks.
Have you tried setting the other options in http://www.erlang.org/doc/man/inet.html#setopts-2
inet:setopts(AcceptSocket, [{active, true}])
for example:
{packet, line} to read in a line at a time
and
binary to read in data as a binary.
I also was working through a similar exercise based on that tutorial recently and my options used were:
inet:setopts(LSocket, [{active,true}, {packet, line}, binary, {reuseaddr, true}]),
To conclude, watch out for the options. I was indeed not paying attention to the implications of the set of options. I tried with a more narrowed down situation and worked it out. My problem was the {packet, line} option which implies that \n is considered a message delimiter.