Erlang/OTP Forums

Author Message

<  Advanced Erlang/OTP  ~  gen_tcp : client/server

klm
Posted: Wed May 13, 2009 8:59 pm Reply with quote
User Joined: 11 May 2009 Posts: 18
hey !

I try to communicate between a client and a server using gen_tcp

I create my server with gen_tcp:listen and accept the client (gen_tcp:connect) with gen_tcp:accept

I send a message to my server and it receives the message, to confirm the reception I would like to send a message from my server to my client but I've got an error I can't explain.

I use this in my client to receive the message

case gen_tcp:recv(Socket,0) of
{ok, Data} ->
io:format("RECEPTION ~p~n",[Data]);

{error, Closed} ->
gen_tcp:close(Socket)
end.

and I've got this error :

** exception exit: undef
in function program:recept/1
called as program:recept(#Port<0.1974>)

=ERROR REPORT==== 13-May-2009::22:47:58 ===
Error in process <0.134.0> with exit value: {undef,[{program,recept,[#Port<0.1974>]}]}

could help me please with this problem.

I asking me if as a client I can use the function gen_tcp:recv or I could just send.

Thanks !
View user's profile Send private message
Cy6erBr4in
Posted: Thu May 14, 2009 5:50 am Reply with quote
Joined: 16 Oct 2008 Posts: 9
Hello. It would be better if you show your code (both modules - client and server).
View user's profile Send private message
klm
Posted: Thu May 14, 2009 9:16 am Reply with quote
User Joined: 11 May 2009 Posts: 18
my code

server :

new() ->
case inet:gethostname() of
{ok,Nom} -> io:format("Hostname : ~p~n",[Nom])
end,


{ok,Addr} = inet:getaddr(Nom,inet),
io:format("Adresse Ip : ~p~n",[Addr]),


SocketDecoute = case gen_tcp:listen(?default_port, [{ip,Addr},{packet,0}, {active,false},{reuseaddr,false}]) of
%%accès possible
{ok,LSock} -> io:format("Serveur démarré sur le port ~p~n",[?default_port]),
LSock;
%%une erreur s'est produite
{error, Reason} -> io:format("Error on port ~p : [~p]~n",[?default_port, Reason]),
exit(Reason)
end,



spawn(?MODULE, server, [SocketDecoute]).

stop(Pid) ->
Pid ! {stop},
ok.
%ecrit un ok a la fin


server(LSock) ->
process_flag(trap_exit, true),
loop(LSock).


loop(LSock)->

receive
{stop} ->
io:format("Serveur arrêté~n",[]),
exit(normal);
{'EXIT',Pid,Raison} ->
io:format("Un client vient de se déconnecter~n",[])
after 100 ->
timeout

end,


case gen_tcp:accept(LSock,100) of
{ok,Sock} ->
io:format("Connexion d'un nouveau client ~n",[]),
{ok,{Ip_client,Port_client}} = inet:peername(Sock),
io:format("Adresse Ip du client : ~p~n",[Ip_client]),
PClientID = spawn_link(?MODULE, client_manager, [Sock]),
loop(LSock);

{error, timeout} ->
loop(LSock)
end.


client_manager(Socket) ->
client_manager(Socket,[]).

client_manager(Socket, Tampon) ->
case gen_tcp:recv(Socket,0) of
{ok, Donnees} ->
io:format("NOM DU JOUEUR : ~p~n",[Donnees]),
gen_tcp:send(Socket,"RECEPTION DES DONNEES");

{error, closed} ->
gen_tcp:close(Socket)
end.



and for the client :

rejoin(Ip) ->
{ok,Parsed_Ip} = inet_parse:address(Ip),
Socket = case gen_tcp:connect(Parsed_Ip,?default_port,[{packet,0},{active,true},{reuseaddr,true}],infinity) of
{ok,Sock} ->
io:format("Connexion à ~p ...~n",[Ip]),
Sock;
{error,Raison} -> io:format("Erreur de connexion [~p]~n",[Raison]),
exit(Raison)
end,

comm(Socket),


gen_tcp:close(Socket).

comm(Socket) ->
io:format("PLAYER NAME : "),
Line = io:get_line('> '),
Message = "NVP " ++ [Line],
gen_tcp:send(Socket,Message),
WClientID = spawn_link(?MODULE, recevoir, [Socket]).

recevoir(Socket) ->
case gen_tcp:recv(Socket,0) of
{ok, Data} ->
io:format("RECEPTION ~p~n",[Data]);

{error, closed} ->
gen_tcp:close(Socket)
end.
View user's profile Send private message
Cy6erBr4in
Posted: Thu May 14, 2009 11:05 am Reply with quote
Joined: 16 Oct 2008 Posts: 9
OK, let`s see...

klm wrote:
my code
...
and for the client :
...
comm(Socket),

gen_tcp:close(Socket).

are you sure, you should close Socket here?

because here:
klm wrote:

comm(Socket) ->
...
WClientID = spawn_link(?MODULE, recevoir, [Socket]).

recevoir(Socket) ->
case gen_tcp:recv(Socket,0) of
{ok, Data} ->
io:format("RECEPTION ~p~n",[Data]);

you will try to receive data from closed socket, won`t you?

let me to explain...

you call function
comm(Socket)
when you return from this funciton, socket will be closed, OK...

in this function (comm) you spawn new process, and this process will be waiting for data from the same socket which will be closed immediately after returning from comm function.

I`m not quite sure, but it`s my point of view. I`ll try to run your code and make some changes.
View user's profile Send private message
Cy6erBr4in
Posted: Thu May 14, 2009 11:40 am Reply with quote
Joined: 16 Oct 2008 Posts: 9
So, one more thing, you should use gen_tcp:connect with {active, false} in client too.
you could get more information about options here:

http://erlang.org/doc/man/inet.html#setopts-2

Quote:

{active, true | false | once}
If the value is true, which is the default, everything received from the socket will be sent as messages to the receiving process. If the value is false (passive mode), the process must explicitly receive incoming data by calling gen_tcp:recv/2,3 or gen_udp:recv/2,3 (depending on the type of socket).


I have just tried it, and it works! Smile

Good luck!
View user's profile Send private message
klm
Posted: Thu May 14, 2009 5:04 pm Reply with quote
User Joined: 11 May 2009 Posts: 18
ok thanks for your help.

I will try tonight.

I will post after if it works (or don't Smile )
View user's profile Send private message
klm
Posted: Thu May 14, 2009 7:30 pm Reply with quote
User Joined: 11 May 2009 Posts: 18
ok thanks for your help !

it works !

not at the first try but with your 2 posts I finally understand resolve the problem.


thanks again.
View user's profile Send private message
Cy6erBr4in
Posted: Thu May 14, 2009 7:32 pm Reply with quote
Joined: 16 Oct 2008 Posts: 9
You`re welcome! Smile
View user's profile Send private message
wuji
Posted: Sat Aug 11, 2012 1:38 am Reply with quote
User Joined: 10 Aug 2012 Posts: 654
for your appeal. There are really only three basic basic cheap replica *beep* basic arguments you can make to appeal your tax assessment.
keeps it nice and simple. See if one applies:1. The The replica designer *beep* The assessor made a mistake in describing your house. This
covers situations where the assessor made simple math mistakes. Maybe Maybe cheap Ralph Lauren Polo Maybe he got the square footage wrong (only heated, livable
should be counted), or stated that you have five bedrooms bedrooms cheap designer *beep* bedrooms when you have three. If you uncover these errors,
you – you've just upped your chances of a slam slam replica designer bags for sale slam dunk win. All you have to do is gather
and describe the errors in writing or in person.2. You You cheap replica *beep* You just bought the house for less. If you recently
View user's profile Send private message

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum