How to connect to socket by TCP - sockets

I have simple server on OpenShift by Erlang, which creates socket and wait new connections. Local ip for server is 127.10.206.129 and server listens 16000 port.
Code of my server:
-module(chat).
-export ([start/0, wait_connect/2, handle/2]).
start() ->
{ok, ListenSocket} = gen_tcp:listen(16000, [binary, {ip,{127,10,206,129}}]),
wait_connect(ListenSocket, 0).
wait_connect(ListenSocket, Count) ->
io:format("~s~n", ["Wait..."]),
gen_tcp:accept(ListenSocket),
receive
{tcp, _Socket, Packet} ->
handle(Packet, Count),
spawn(?MODULE, wait_connect, [ListenSocket, Count+1]);
{tcp_error, _Socket, Reason} ->
{error, Reason}
end.
Code of my client:
-module(client).
-export ([client/2]).
client(Host, Data) ->
{ok, Socket} = gen_tcp:connect(Host, 16000, [binary]),
send(Socket, Data),
ok = gen_tcp:close(Socket).
send(Socket, <<Data/binary>>) ->
gen_tcp:send(Socket, Data).
Server starts without troubles. I tried run client on my localhost and had error (it tried to connect for time much than timeout:
2> client:client("chat-bild.rhcloud.com", <<"Hello world!">>).
** exception error: no match of right hand side value {error,etimedout}
in function client:client/2 (client.erl, line 4)
I tried this stupid way (although 127.10.206.129 is a incorrect ip, because it's server local ip):
3> client:client({127,10,206,129}, <<"Hello world!">>).
** exception error: no match of right hand side value {error,econnrefused}
in function client:client/2 (client.erl, line 16)
How to do gen_tcp:connect with url?

Only ports 80, 443, 8000, and 8443 are open to the outside world on openshift. You can not connect to other ports on OpenShift from your local workstation, unless you use rhc port-forward command, and that will only work with published ports that are used by cartridges.

Your listen call is limiting the listen interface to 127.10.206.129, but judging from the second client example, your client can't connect to that address. Try eliminating the {ip,{127,10,206,129}} option from your listen call so that your server listens on all available interfaces, or figure out what interface the server name "chat-bild.rhcloud.com" corresponds to and listen only on that interface.

Related

Unable to establish connection to a tcp socket server on aws ec2

I am trying to run a socket server on an aws ec2 ubuntu instance and then connecting with it using my local machine. I was successful with sending HTTP GET requests to my server hosted on aws ec2 instance and getting a response, but I am unable to connect the server and client using sockets, even after enabling custom TCP on the complete range of ports on the instance.
Here is a screenshot describing my instance's inbound and outbound rules :
screenshot
I used this python code from the internet to test socket networking :
socket_client.py :
import socket
def client_program():
host = "<aws instance public ip address>"
port = 8080 # socket server port number
client_socket = socket.socket() # instantiate
client_socket.connect((host, port)) # connect to the server
message = input(" -> ") # take input
while message.lower().strip() != 'bye':
client_socket.send(message.encode()) # send message
data = client_socket.recv(1024).decode() # receive response
print('Received from server: ' + data) # show in terminal
message = input(" -> ") # again take input
client_socket.close() # close the connection
if __name__ == '__main__':
client_program()
socket_server.py :
import socket
def server_program():
host = "0.0.0.0"
port = 8080 # initiate port no above 1024
server_socket = socket.socket() # get instance
# look closely. The bind() function takes tuple as argument
server_socket.bind((host, port)) # bind host address and port together
# configure how many client the server can listen simultaneously
server_socket.listen(2)
conn, address = server_socket.accept() # accept new connection
print("Connection from: " + str(address))
while True:
# receive data stream. it won't accept data packet greater than 1024 bytes
data = conn.recv(1024).decode()
if not data:
# if data is not received break
break
print("from connected user: " + str(data))
data = input(' -> ')
conn.send(data.encode()) # send data to the client
conn.close() # close the connection
if __name__ == '__main__':
server_program()
Note that the socket server-client are working completely fine when run on my local machine.
Please help if you know about how to fix this .
Edit - I have also tried with disabling firewall on the linux ec2 instance, but the problem still persists.
Thanks.

domain socket address already in use problem

I have two processes communicating through the domain socket. Both server and client socket addresses are set to an abstract socket address.
If client process crashes or be killed, the return value of recvmsg() in the server will get 0 or -1. My code handles these two returned value in the different ways, which are
return 0 (work fine)
server closes connection fd which generated by accept() and waits for another client connection (by accept())
return -1
I got the errno ECONNRESET and the server will close both fds (which generated by socket() and accept()). Then the server will try to restart all socket related connection ( socket() -> unlink() -> bind() -> listen() -> accept()). I fail to bind() the same address and get the errno EADDRINUSE.
My questions are
Is my procedure to handle the ECONNRESET correct?
Why I get EADDRINUSE even if I close the fd before? ( I've checked the return value of close(), it close successfully.)
It is possible when the client side doesn't close the fd (generated by connect()). Then the server will see the address is used?
I want the know the correct way to handle the ECONNRESET without restarting the process.
Thank you for your time!

LibGDX: Error making a socket connection to *ip-adress*

I want to make 2 devices communicate via sockets.
I use this code for the client socket:
Socket socket = Gdx.net.newClientSocket(Net.Protocol.TCP, adress, 1337, socketHints);
(SocketHints: timeout = 4000)
I get a GdxRuntimeException each time this line is being executed. What is wrong with the socket?
Screenshot of stack trace
You get that message because the socket couldn't be opened.
Note the last line about the return in the API:
newClientSocket:
Socket newClientSocket(Net.Protocol protocol,
java.lang.String host,
int port,
SocketHints hints)
Creates a new TCP client socket that connects to the given host and port.
Parameters:
host - the host address
port - the port
hints - additional SocketHints used to create the socket. Input null to use the default setting provided by the system.
Returns:
GdxRuntimeException in case the socket couldn't be opened
Try doing some debugging to find out why you are getting this error.
Is the port already in use? Are you trying to open more than one connection on the same port? Is the server IP valid? Maybe something else is causing the issue?

Erlang socket and receive timeout

How to set receive timeout for socket, i could not find it in the socket option man.
my first soluation to the problem is to put after statement.
{ok, Listen} = gen_tcp:listen(Port, [..,{active, once}...]),
{ok, Socket} = gen_tcp:accept(Listen),
loop(Socket).
loop(Socket) ->
receive
{tcp, Socket, Data} ->
inet:setopts(Sock, [{active, once}]),
loop(Socket);
{tcp_closed, Socket} -> closed;
Other -> process_data(Other)
after 1000 -> time_out
end.
but the socket may never timeout because there are messages from other processes
how can i set timeout without spawning other process ?
You can't specify a receive timeout if you are using active mode. If you need to control receive timeout behavior, switch to passive mode on the socket, i.e. {active,false} on the socket options, and then use gen_tcp:recv with a receive timeout option.
In addition, a lot of Erlang socket server designs use an Erlang process per client connection. You can see http://www.trapexit.org/Building_a_Non-blocking_TCP_server_using_OTP_principles and http://20bits.com/article/erlang-a-generalized-tcp-server for examples. The OTP provides a lot of great ways to build robust servers with Erlang; take advantage of it!
also you can use prim_inet:async_recv/3 which allow you to receive tcp message with timeout while receving other messages from different processes
read(Socket) ->
prim_inet:async_recv(Socket, 0, 1000),
receive
{inet_async, _ ,_ ,{ok, Msg}} ->
io:format("message received ~p~n",[Msg]),
read(Socket);
{inet_async,_,_,{error,timeout}} ->
io:format("timeout !"),
catch gen_tcp:close(Socket);
{fake, Msg} -> io:format("Message = ~p~n", [Msg]),
read(Socket)
end.

Determining IP address and port of an incoming TCP/IP connection in Erlang

I would like to fetch the IP address and port number of an incoming TCP/IP connection. Unfortunately gen_tcp's accept and recv functions only give back a socket, while gen_udp's recv function also gives back the address information. Is there a straightforward way to collect address information belonging to a socket in Erlang?
You need inet/peername 1. From the Erlang inet docs:
peername(Socket) -> {ok, {Address, Port}} | {error, posix()}
Types:
Socket = socket()
Address = ip_address()
Port = int()
Returns the address and port for the other end of a connection.