Can someone help me with my gen_server assignment please?

I’m new to erlang and i’m confused on what to do for my gen_server assignment - can anyone help me please?

This assignment consists of three program components which are to be named as follows:

chat_server.erl – This is a gen_server module that acts as a chat server. It must maintain a list of connected clients and handle incoming messages.

chat_client.erl – This is a client module that connects to the chat server and both sends and receives messages.

chat_script.erl – This is code that starts the server and multiple client processes. You may hard-code the number of clients to a convenient number but should be at least three.

To facilitate getting started, chat_script.erl should look something like this:

%%% chat_script.erl %%%

-module(chat_script).

-export([start/0]).

start() ->

    ChatServer = chat_server:start_link(),

    ChatClient1 = chat_client:start_link(),

    ChatClient2 = chat_client:start_link(),

    chat_client:connect(ChatServer),

    chat_client:connect(ChatServer),

    chat_client:send_message(ChatClient1, "Hello from client 1!"),

    chat_client:send_message(ChatClient2, "Hello from client 2!").

1 Like

Hello

I don’t know if you are using an OTP application but I think it would be convenient :slight_smile:

and, in order to let us help you, could you share your error or what is not convincing you?

What school do you go to? I wish I went there… Or is it job related?

chat_server.erl can refer to the https://github.com/imboy-pub/imboy/blob/main/src/websocket_handler.erl

It is based on cowboy_websocket https://github.com/ninenines/cowboy/blob/master/src/cowboy_websocket.erl

cowboy_websocket Although not gen_server; But I think it’s a variant of gen_server that suits your needs

chat_client.erl conforms to the websocket protocol can be, their own google, many very

chat_script.erl, I understand should be corresponding to the https://github.com/imboy-pub/imboy/blob/main/src/imboy_sup.erl

Cowboy is very good, you can first take a look at its documentation (Nine Nines: Cowboy User Guide), look at the source code, it is a very good learning materials

1 Like

Since it seems your restraints are to three modules, I would only look at any cowboy stuff just for reference. The cowboy application is not a small and trivial OTP application, and you are needing something more toy-like. Google around for some textbook erlang message passing examples. You should use gen_server in real life, but you’d learn more if you rolled your own. For the server part, take a look at this post I just wrote this week: Erlang, the Unix way

The part you should pay no attention in there is the escript stuff, but even the client code could get you going.

But if your assignment requires gen_server to be used, then again, only use that post for reference… it’s not going to cut it for you.

P.S. If you lift some of the server code, you can take out the loop buffer stuff, and also avoid the trim routines.

I often want to use Erlang from Unix scripts, too! Super useful. I often spool up some kind of server at the start of a semester and then use (and have students use) escripts to interact with it. I mostly do this for fairly rare events (like students with serious emergencies who need a way to submit work around the usual system).

I solve the cookie issue differently: rather than bake it into the scripts, I have a separate module (available from ERL_LIBS) that exports an ensure_cookie/0 that sets the cookie.

What prevents me from using this for everyday things is the node name problem. I can’t have two students on the same machine run the script at the same time, because Erlang doesn’t allow to nodes with the same name. I don’t want to gensym a node name, because node names are atoms and thus never GCed, and I don’t want my server to run out of space after many thousands of students requests (maybe I overestimate this problem).

I’ve learned there are “anonymous nodes” now that generate a new name each time. Maybe they are handled in a way that they doesn’t make the server permanently “intern” the atoms. I don’t know.

If you know, or find out, I’d be interested to hear! :slight_smile:

Welcome to Erlang!

I teach a course with an assignment almost exactly like this, minus the chat_script. I have the client code have a function that starts a recursive function that reads lines and sends them to the server, which them sends each client line to all the other clients.

Students often wrestle with gen_servers. I think a big problem is understanding what code runs where/when — they find the callback model of OTP code a bit challenging. For this reason, I usually have them write a chat server and client manually, and then use gen_server.

My advice is, as with any large problem, to break it into pieces, and don’t be afraid to experiment or put in temporary bits of code (including debug print statements — I’m old school :slight_smile:).

I’ll make some suggestions, but you can do whatever works for you. Maybe this will get you out of the gate…

Maybe start with the server. For a server, you need to know the server’s state and its message protocol, which encodes what operations the server supports. The operations come in two flavors: server administration (which is usually start and/or start_link and stop) and operations clients will need.

For a chat server, clients should at least be able to join/subscribe to a chat room and send messages to the room. It looks as if your server is just a single room. Maybe there is a way for them to leave the room, too. You can decide whether these operations are calls or casts, i. e., whether a client needs to await a response. If you aren’t sure, pick one. You can change it later.

For the server state, you’ll need to pick a data structure that can keep track of the clients in a way that would allow the server to send a message a client sends to the server to all the other clients in the room.

That should get you started.

In general, the way I suggest building this out is to start with a server that does nothing: basically, the gen_server out of the box. Then add default handlers for calls and casts that print out “unhandled call/cast: …” for any message. Just define those: initially, all calls and casts will be unhandled. Then I add a call that returns the state, which I can remove later. This will let you start the server in the Erlang shell, ask it for its state any time, and see any unhandled message.

Once that works, I would start adding some real call and/or cast handlers, one at a time. Invoke each one getting the state before and after. Maybe have the server mock up stuff you haven’t figured out yet ("will send message to other clients her).

Once you can add a client this way, you can start another Erlang shell in another terminal and try to add a second client.

Once you can do this, you can use what you were typing into the shells as the start of your client module’s code.

I have some not very polished notes based on stuff I go over in class, and you are welcome to have a look. Please don’t expect support :slight_smile: gen_server overview and Getting started with gen_servers. (The assignments and solutions are not available on the web now, and that’s on purpose.) Again, this is pretty rough, but if you are feeling stuck, it may help get moving!

I hope this is useful. Don’t forget to enjoy the ride! Programming in Erlang is super fun!

3 Likes

What’s the school/university?

Tufts University in Medford, Massachusetts, USA.
The course is on Concurrent Programming. It’s project based. I cover conventional, shared memory threads for about a month, then do natively concurrent programming using Actors (in Erlang) for a month. Then students propose and implement team projects for the rest of the term.

used to be taught once a year as an elective, but it’s unfortunately less regular these days, because I’ve picked up another course that is a requirement in another program. I’ll get it back on the schedule, though — I enjoy teaching it!

2 Likes

Excellent! Glad OTP is stateside at some fine schools!

3 Likes