Клиент-Сервер: приватные сообщения в чате - C#
Формулировка задачи:
Добрый вечер. Делая приложения Клиент-Сервер на чистых сокетах, столкнулся с несколькими проблемами, прошу помощи в решении их. У программы есть своя БД. В программе хочу реализовать чат. Так вот, в общую комнату отправляю сообщение, а вот что бы отправить приватное сообщение как быть??? Сервер должен конектится к этому пользователю простым конектом??? или нужно создавать новый сокет и через него привязываться??? И еще небольшая проблема в сторону остановки сервера. Никак не могу понять как можно остановить асинхронную работу сервера? Я не прошу писать программу, прошу направления на устранения этих проблем.
Решение задачи: «Клиент-Сервер: приватные сообщения в чате»
textual
Листинг программы
using System;
using System.Collections.Generic;
using System.Text;
public class Server
{
public delegate void StartListenerEventHanlder(object sender, EventArgs e);
public event StartListenerEventHanlder StartListener;
public delegate void EndListenerEventHanlder(object sender, EventArgs e);
public event EndListenerEventHanlder EndListener;
public delegate void ReceiveDataEventHandler(object sender, ReceiveDataEventArgs e);
public event ReceiveDataEventHandler ReceiveData;
public delegate void ConnectedSocketEventHanlder(object sender, ConnectedSocketEventArgs e);
public event ConnectedSocketEventHanlder ConnectedSocket;
public delegate void DisconnectedSocketEventHandler(object sender, DisconnectedSocketEventArgs e);
public event DisconnectedSocketEventHandler DisconnectedSocket;
private System.Net.Sockets.TcpListener TcpListener;
private System.Threading.SynchronizationContext Current;
private System.Collections.Generic.Dictionary<System.Net.EndPoint, System.Net.Sockets.Socket> DefaultClients = new System.Collections.Generic.Dictionary<System.Net.EndPoint, System.Net.Sockets.Socket>();
public Server() { }
public bool IsListener { get; private set; }
public void Start(System.Net.IPEndPoint endPoint)
{
if (TcpListener == null)
{
DefaultClients.Clear();
Current = System.Threading.SynchronizationContext.Current;
TcpListener = new System.Net.Sockets.TcpListener(endPoint);
TcpListener.Start();
System.Threading.Thread T = new System.Threading.Thread(OnAcceptSockets);
T.IsBackground = true; T.Start(); IsListener = true;
if (StartListener != null) StartListener.Invoke(this, new EventArgs());
}
}
public void Stop()
{
if (TcpListener != null)
{
IsListener = false; TcpListener.Stop(); TcpListener = null;
DefaultClients.Clear(); EndListener.Invoke(this, new EventArgs());
}
}
public System.Collections.Generic.Dictionary<System.Net.EndPoint, System.Net.Sockets.Socket> Clients { get { return DefaultClients; } }
private void OnAcceptSockets()
{
while (IsListener)
{
try
{
System.Net.Sockets.Socket AcceptSocket = TcpListener.AcceptSocket();
DefaultClients.Add(AcceptSocket.RemoteEndPoint, AcceptSocket);
if (ConnectedSocket != null) ConnectedSocket.Invoke(this, new ConnectedSocketEventArgs(AcceptSocket));
System.Threading.Thread T = new System.Threading.Thread(OnReceiveSocket);
T.IsBackground = true;
T.Start(AcceptSocket);
}
catch { }
}
}
private void OnReceiveSocket(object e)
{
System.Net.Sockets.Socket ClientSocket = (System.Net.Sockets.Socket)e;
System.Net.EndPoint RemoteEndPoint = ClientSocket.RemoteEndPoint;
int ReceiveLength;
int BufferLength = 255;
byte[] BufferReceive = new byte[BufferLength];
try
{
while (true)
{
ReceiveLength= ClientSocket.Receive(BufferReceive);
if (ReceiveLength == 0) { break; }
Array.Resize(ref BufferReceive, ReceiveLength);
ReceiveDataEventArgs EventArgs = new ReceiveDataEventArgs(RemoteEndPoint, BufferReceive, ClientSocket.Available, ClientSocket);
if (ReceiveData != null) ReceiveData.Invoke(this, EventArgs);
Array.Resize(ref BufferReceive, BufferLength);
}
}
catch { }
DefaultClients.Remove(RemoteEndPoint);
if (DisconnectedSocket != null) DisconnectedSocket.Invoke(this, new DisconnectedSocketEventArgs(RemoteEndPoint));
}
public void KickAll()
{
foreach(System.Net.Sockets.Socket e in DefaultClients.Values )
{
e.Close();
if (DisconnectedSocket != null) DisconnectedSocket.Invoke(this, new DisconnectedSocketEventArgs(e.RemoteEndPoint));
}
DefaultClients.Clear();
}
public void Kick(System.Net.EndPoint e )
{
if (DefaultClients.ContainsKey(e))
{
DefaultClients[e].Close();
DefaultClients.Remove(e);
if (DisconnectedSocket != null) DisconnectedSocket.Invoke(this, new DisconnectedSocketEventArgs(e));
}
}
//отправить приватное сообщение.
public void Send(byte[] buf, System.Net.EndPoint e) { if (DefaultClients.ContainsKey(e)) { DefaultClients[e].Send(buf); } }
//отправить приватное сообщение.
public void Send(string buf, System.Net.EndPoint e) { if (DefaultClients.ContainsKey(e)) { DefaultClients[e].Send(System.Text.Encoding.Default.GetBytes(buf)); } }
public void SendAll(byte[] buf) { foreach (System.Net.Sockets.Socket e in DefaultClients.Values) { e.Send(buf); } }
public void SendAll(string buf) { foreach (System.Net.Sockets.Socket e in DefaultClients.Values) { e.Send(System.Text.Encoding.Default.GetBytes(buf)); } }
public void SendFile(string path, System.Net.EndPoint e) { if (DefaultClients.ContainsKey(e)) { DefaultClients[e].SendFile(path); } }
public void SendFile(string path) { foreach (System.Net.Sockets.Socket e in DefaultClients.Values) { e.SendFile(path); } }
}
public class ReceiveDataEventArgs: EventArgs
{
public ReceiveDataEventArgs(System.Net.EndPoint endPoint, byte[] buf, int available,System.Net.Sockets.Socket sock)
{ RemoteEndPoint = endPoint; Buffer = buf; Available = available; ClientSocket = sock; }
public System.Net.EndPoint RemoteEndPoint { get; private set; }
public byte[] Buffer { get; private set; }
public int Available { get; private set; }
public System.Net.Sockets.Socket ClientSocket { get; private set; }
}
public class ConnectedSocketEventArgs: EventArgs
{
public ConnectedSocketEventArgs(System.Net.Sockets.Socket sock) { ClientSocket = sock; }
public System.Net.Sockets.Socket ClientSocket { get; private set; }
}
public class DisconnectedSocketEventArgs : EventArgs
{
public DisconnectedSocketEventArgs(System.Net.EndPoint endPoint) { RemoteEndPoint = endPoint; }
public System.Net.EndPoint RemoteEndPoint { get; private set; }
}