Skip to content

Commit 68e0d78

Browse files
cleaned up ChatClient / ChatServer sample (#6824)
* removed mutable state on messages * migrated to using record types for all messages * `await` on `ActorSystem` termination * cleaned up styles and formatting
1 parent 608d9e8 commit 68e0d78

File tree

6 files changed

+69
-133
lines changed

6 files changed

+69
-133
lines changed

src/examples/Chat/ChatClient/Program.cs

+41-49
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
using System;
99
using System.Linq;
10+
using System.Threading.Tasks;
1011
using Akka.Actor;
1112
using Akka.Configuration;
1213
using ChatMessages;
@@ -15,7 +16,7 @@ namespace ChatClient
1516
{
1617
class Program
1718
{
18-
static void Main(string[] args)
19+
public static async Task Main(string[] args)
1920
{
2021
var config = ConfigurationFactory.ParseString(@"
2122
akka {
@@ -31,54 +32,50 @@ static void Main(string[] args)
3132
}
3233
");
3334

34-
using (var system = ActorSystem.Create("MyClient", config))
35+
var system = ActorSystem.Create("MyClient", config);
36+
var chatClient = system.ActorOf(Props.Create<ChatClientActor>());
37+
chatClient.Tell(new ConnectRequest("Roggan"));
38+
39+
while (true)
3540
{
36-
var chatClient = system.ActorOf(Props.Create<ChatClientActor>());
37-
chatClient.Tell(new ConnectRequest()
41+
var input = Console.ReadLine();
42+
if (input.StartsWith('/'))
3843
{
39-
Username = "Roggan",
40-
});
44+
var parts = input.Split(' ');
45+
var cmd = parts[0].ToLowerInvariant();
46+
var rest = string.Join(" ", parts.Skip(1));
4147

42-
while (true)
43-
{
44-
var input = Console.ReadLine();
45-
if (input.StartsWith('/'))
48+
if (cmd == "/nick")
4649
{
47-
var parts = input.Split(' ');
48-
var cmd = parts[0].ToLowerInvariant();
49-
var rest = string.Join(" ", parts.Skip(1));
50-
51-
if (cmd == "/nick")
52-
{
53-
chatClient.Tell(new NickRequest
54-
{
55-
NewUsername = rest
56-
});
57-
}
58-
if (cmd == "/exit")
59-
{
60-
Console.WriteLine("exiting");
61-
break;
62-
}
50+
chatClient.Tell(new ChatClientActor.RequestNewNick(rest));
6351
}
64-
else
52+
53+
if (cmd == "/exit")
6554
{
66-
chatClient.Tell(new SayRequest()
67-
{
68-
Text = input,
69-
});
55+
Console.WriteLine("exiting");
56+
break;
7057
}
7158
}
72-
73-
system.Terminate().Wait();
59+
else
60+
{
61+
chatClient.Tell(new ChatClientActor.PushNewChatMessage(input));
62+
}
7463
}
64+
65+
await system.Terminate();
7566
}
7667
}
7768

78-
class ChatClientActor : ReceiveActor, ILogReceive
69+
internal class ChatClientActor : ReceiveActor, ILogReceive
7970
{
8071
private string _nick = "Roggan";
81-
private readonly ActorSelection _server = Context.ActorSelection("akka.tcp://MyServer@localhost:8081/user/ChatServer");
72+
73+
private readonly ActorSelection _server =
74+
Context.ActorSelection("akka.tcp://MyServer@localhost:8081/user/ChatServer");
75+
76+
public record RequestNewNick(string NewNick);
77+
78+
public record PushNewChatMessage(string Message);
8279

8380
public ChatClientActor()
8481
{
@@ -94,30 +91,25 @@ public ChatClientActor()
9491
Console.WriteLine(rsp.Message);
9592
});
9693

97-
Receive<NickRequest>(nr =>
94+
Receive<RequestNewNick>(nr =>
9895
{
99-
nr.OldUsername = _nick;
100-
Console.WriteLine("Changing nick to {0}", nr.NewUsername);
101-
_nick = nr.NewUsername;
102-
_server.Tell(nr);
96+
Console.WriteLine("Changing nick to {0}", nr.NewNick);
97+
var request = new NickRequest(_nick, nr.NewNick);
98+
_nick = nr.NewNick;
99+
_server.Tell(request);
103100
});
104101

105102
Receive<NickResponse>(nrsp =>
106103
{
107104
Console.WriteLine("{0} is now known as {1}", nrsp.OldUsername, nrsp.NewUsername);
108105
});
109106

110-
Receive<SayRequest>(sr =>
107+
Receive<PushNewChatMessage>(sr =>
111108
{
112-
sr.Username = _nick;
113-
_server.Tell(sr);
109+
_server.Tell(new SayRequest(_nick, sr.Message));
114110
});
115111

116-
Receive<SayResponse>(srsp =>
117-
{
118-
Console.WriteLine("{0}: {1}", srsp.Username, srsp.Text);
119-
});
112+
Receive<SayResponse>(srsp => { Console.WriteLine("{0}: {1}", srsp.Username, srsp.Text); });
120113
}
121114
}
122-
}
123-
115+
}

src/examples/Chat/ChatMessages/ChatMessages.csproj

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>$(NetStandardLibVersion)</TargetFramework>
3+
<TargetFramework>$(NetTestVersion)</TargetFramework>
44
</PropertyGroup>
55

6-
<ItemGroup>
7-
<Folder Include="Properties\" />
8-
</ItemGroup>
9-
106
<ItemGroup>
117
<ProjectReference Include="..\..\..\core\Akka\Akka.csproj" />
128
</ItemGroup>

src/examples/Chat/ChatMessages/Messages.cs

+15-32
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,24 @@
55
// </copyright>
66
//-----------------------------------------------------------------------
77

8-
using Akka.Actor;
9-
108
namespace ChatMessages
119
{
12-
public class ConnectRequest
13-
{
14-
public string Username { get; set; }
15-
}
16-
17-
public class ConnectResponse
18-
{
19-
public string Message { get; set; }
20-
}
21-
22-
public class NickRequest
23-
{
24-
public string OldUsername { get; set; }
25-
public string NewUsername { get; set; }
26-
}
10+
/// <summary>
11+
/// Marker interface for all chat messages exchanged between client and server
12+
/// </summary>
13+
/// <remarks>
14+
/// Currently not used for anything - can be used in the future for serialization
15+
/// or routing purposes.
16+
/// </remarks>
17+
public interface IChatProtocol { }
18+
19+
public record ConnectRequest(string Username) : IChatProtocol;
2720

28-
public class NickResponse
29-
{
30-
public string OldUsername { get; set; }
31-
public string NewUsername { get; set; }
32-
}
21+
public record ConnectResponse(string Message) : IChatProtocol;
3322

34-
public class SayRequest
35-
{
36-
public string Username { get; set; }
37-
public string Text { get; set; }
38-
}
23+
public record NickRequest(string OldUsername, string NewUsername) : IChatProtocol;
24+
public record NickResponse(string OldUsername, string NewUsername) : IChatProtocol;
25+
public record SayRequest(string Username, string Text) : IChatProtocol;
3926

40-
public class SayResponse
41-
{
42-
public string Username { get; set; }
43-
public string Text { get; set; }
44-
}
27+
public record SayResponse(string Username, string Text) : IChatProtocol;
4528
}

src/examples/Chat/ChatServer/App.config

-20
This file was deleted.

src/examples/Chat/ChatServer/ChatServer.csproj

-4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,4 @@
1010
<ProjectReference Include="..\ChatMessages\ChatMessages.csproj" />
1111
</ItemGroup>
1212

13-
<ItemGroup>
14-
<Folder Include="Properties\" />
15-
</ItemGroup>
16-
1713
</Project>

src/examples/Chat/ChatServer/Program.cs

+12-23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
using System;
99
using System.Collections.Generic;
10+
using System.Threading.Tasks;
1011
using Akka.Actor;
1112
using Akka.Configuration;
1213
using ChatMessages;
@@ -15,7 +16,7 @@ namespace ChatServer
1516
{
1617
class Program
1718
{
18-
static void Main(string[] args)
19+
public static async Task Main(string[] args)
1920
{
2021
var config = ConfigurationFactory.ParseString(@"
2122
akka {
@@ -32,51 +33,39 @@ static void Main(string[] args)
3233
}
3334
");
3435

35-
using (var system = ActorSystem.Create("MyServer", config))
36-
{
37-
system.ActorOf(Props.Create(() => new ChatServerActor()), "ChatServer");
36+
var system = ActorSystem.Create("MyServer", config);
37+
38+
system.ActorOf(Props.Create(() => new ChatServerActor()), "ChatServer");
3839

39-
Console.ReadLine();
40-
}
40+
Console.ReadLine();
41+
await system.Terminate();
4142
}
4243
}
4344

44-
class ChatServerActor : ReceiveActor, ILogReceive
45+
internal class ChatServerActor : ReceiveActor, ILogReceive
4546
{
4647
private readonly HashSet<IActorRef> _clients = new();
4748

4849
public ChatServerActor()
4950
{
5051
Receive<SayRequest>(message =>
5152
{
52-
var response = new SayResponse
53-
{
54-
Username = message.Username,
55-
Text = message.Text,
56-
};
53+
var response = new SayResponse(message.Username, message.Text);
5754
foreach (var client in _clients) client.Tell(response, Self);
5855
});
5956

6057
Receive<ConnectRequest>(_ =>
6158
{
6259
_clients.Add(Sender);
63-
Sender.Tell(new ConnectResponse
64-
{
65-
Message = "Hello and welcome to Akka.NET chat example",
66-
}, Self);
60+
Sender.Tell(new ConnectResponse("Hello and welcome to Akka.NET chat example"), Self);
6761
});
6862

6963
Receive<NickRequest>(message =>
7064
{
71-
var response = new NickResponse
72-
{
73-
OldUsername = message.OldUsername,
74-
NewUsername = message.NewUsername,
75-
};
65+
var response = new NickResponse(message.OldUsername, message.NewUsername);
7666

7767
foreach (var client in _clients) client.Tell(response, Self);
7868
});
7969
}
8070
}
81-
}
82-
71+
}

0 commit comments

Comments
 (0)