🛡 Messenger for local networks, built in pure C# using TCP/IP, MySQL, and WPF.
- 🔐 User authentication and registration
- 💬 Personal and group chats
- 📎 File and image sharing
- 👥 Online/offline user statuses
- 🎨 Modern dark-themed UI inspired by Telegram
- .NET 8
- WPF (desktop client)
- TCP/IP
- MySQL with Entity Framework
- Newtonsoft.Json
- SHA-256
MessengerApp/
– WPF client applicationMessengerServer/
– Console-based serverMessengerClientTEST/
– Test client (used for debugging and connection testing)
The server is built on top of raw TCP using TcpListener
and handles clients with a custom ClientHandler
. Below is a simplified version of the main server loop:
public void Start()
{
_listener.Start();
ServerIsRunning = true;
Console.WriteLine("Server is running...");
while (ServerIsRunning)
{
var clientSocket = _listener.AcceptTcpClient();
Console.WriteLine("Client connected");
var clientHandler = new ClientHandler(clientSocket, this, _userService, _groupChatService, _personalChatService);
Task.Run(async () =>
{
try
{
await clientHandler.HandleClient();
}
catch (Exception ex)
{
Console.WriteLine($"Client error: {ex.Message}");
}
});
}
}
Each client is handled by a ClientHandler
instance that processes commands in a loop.
Here's a simplified excerpt showing how user login and registration are managed:
public async Task HandleLoginAsync(string[] parts)
{
if (parts.Length < 3)
{
await SendMessageAsync("LOGIN_FAILED", "Некоректний формат");
return;
}
string username = parts[1], password = parts[2];
var user = await _userService.AuthenticateUserAsync(username, password);
if (user != null)
{
UserId = user.Id;
ThisUser = user;
_server.AddConnectedClient(UserId, this);
Name = user.Name;
Surname = user.Surname!;
Avatar = user.AvatarImage;
await SendMessageAsync("LOGIN_SUCCESS", "Авторизація успішна", UserId);
}
else
{
await SendMessageAsync("LOGIN_FAILED", "Невірний логін або пароль", 0);
}
}
This is a simplified example of how the client connects to the server and logs in using TCP streams with BinaryReader/Writer:
public async Task<bool> ConnectAsync()
{
var config = ReadConfig();
_client = new TcpClient();
await _client.ConnectAsync(config.IpAddress, config.Port);
if (_client.Connected)
{
_stream = _client.GetStream();
_reader = new BinaryReader(_stream, Encoding.UTF8);
_writer = new BinaryWriter(_stream, Encoding.UTF8);
return true;
}
return false;
}
public async Task<(bool success, string message)> LoginAsync(string username, string password)
{
if (!Connected)
return (false, "Not connected to server.");
lock (_streamLock)
{
_writer!.Write($"LOGIN|{username}|{password}");
_writer.Flush();
string responseType = _reader!.ReadString();
string responseMessage = _reader.ReadString();
UserId = _reader.ReadInt32();
if (responseType == "LOGIN_SUCCESS")
Username = username;
return responseType == "LOGIN_SUCCESS"
? (true, responseMessage)
: (false, responseMessage);
}
}
- Start the MessengerServer project.
- Launch the MessengerApp (WPF client).
- Make sure the client reads the correct
IP
andPort
fromconfig.json
. - Register a new user or log in with existing credentials.
Under active development. Planned features include real-time messaging, emoji support, notifications, and better error handling.
This repository serves as a portfolio preview of the Messenger project.
The full source code is not publicly available to prevent misuse, but a demo or access for review can be provided upon request.
Andriy Khodakivskiy
Private GitHub repository – not open for public use yet.