220 lines
7.7 KiB
C#
220 lines
7.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
|
|
using BeWo.Data;
|
|
using BeWo.Data.Access;
|
|
using BeWo.Data.Entities;
|
|
|
|
using BS.Shared;
|
|
|
|
namespace BeWoChatServer
|
|
{
|
|
public class Server
|
|
{
|
|
// Fehlercodes zwischen 1000 und 1499
|
|
//TODO: Login hier implementieren und das andere Projekt löschen
|
|
|
|
private static readonly object _Lock = string.Empty;
|
|
|
|
private static readonly Dictionary<Socket, long> clientList = new Dictionary<Socket, long>();
|
|
protected static Socket serverSocket;
|
|
|
|
private static AsyncCallback asyncCallback;
|
|
|
|
private static int clientCount;
|
|
|
|
public static void Main(string[] args)
|
|
{
|
|
try
|
|
{
|
|
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
var server = new IPEndPoint(IPAddress.Any, 5000);
|
|
|
|
serverSocket.Bind(server);
|
|
serverSocket.Listen(4);
|
|
|
|
serverSocket.BeginAccept(OnClientConnected, null);
|
|
|
|
while (true) { }
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.WriteLine("ChatServerException (1010): " + e.Message);
|
|
}
|
|
}
|
|
|
|
public static void OnClientConnected(IAsyncResult asyncResult)
|
|
{
|
|
try
|
|
{
|
|
var workerSocket = serverSocket.EndAccept(asyncResult);
|
|
|
|
Interlocked.Increment(ref clientCount);
|
|
|
|
clientList.Add(workerSocket, 0);
|
|
|
|
WaitForClientData(workerSocket, "", 0, 0);
|
|
|
|
serverSocket.BeginAccept(OnClientConnected, null);
|
|
}
|
|
catch (SocketException e)
|
|
{
|
|
Debug.WriteLine("ChatServerException (1020): " + e.Message);
|
|
}
|
|
}
|
|
|
|
public static void WaitForClientData(Socket socket, string clientName, long oid, long recipientPersonOid)
|
|
{
|
|
try
|
|
{
|
|
if (asyncCallback == null)
|
|
{
|
|
asyncCallback = OnReceiveData;
|
|
}
|
|
|
|
var packet = new Packet(socket, clientName, oid, recipientPersonOid);
|
|
|
|
socket.BeginReceive(packet.DataBuffer, 0, packet.DataBuffer.Length, SocketFlags.None, asyncCallback, packet);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.WriteLine("ChatServerException (1030): " + e.Message);
|
|
}
|
|
}
|
|
|
|
public static void OnReceiveData(IAsyncResult asyncResult)
|
|
{
|
|
var dataPacket = (Packet) asyncResult.AsyncState;
|
|
|
|
try
|
|
{
|
|
var responseByteCount = dataPacket.Socket.EndReceive(asyncResult);
|
|
|
|
var chars = new char[responseByteCount];
|
|
|
|
var decoder = Encoding.UTF8.GetDecoder();
|
|
decoder.GetChars(dataPacket.DataBuffer, 0, responseByteCount, chars, 0);
|
|
|
|
if(chars.Count(f => f.Equals(';')) >= 4)
|
|
{
|
|
var message = new string(chars);
|
|
|
|
dataPacket.GetData(message);
|
|
}
|
|
|
|
switch(dataPacket.DataIdentifier) {
|
|
case DataIdentifier.Login:
|
|
var endPoint = dataPacket.Socket.RemoteEndPoint;
|
|
|
|
var endPointCollection = clientList.Select(s => s.Key.RemoteEndPoint).ToList();
|
|
|
|
var istEnthalten = endPointCollection.Contains(endPoint);
|
|
if(istEnthalten)
|
|
{
|
|
clientList[dataPacket.Socket] = dataPacket.SenderPersonOid;
|
|
}
|
|
|
|
var notificationPacket = new Packet(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, 0) {DataIdentifier = DataIdentifier.StatusNotificationLogin};
|
|
|
|
foreach (var client in clientList.Where(w => !w.Value.Equals(dataPacket.SenderPersonOid)))
|
|
{
|
|
client.Key.Send(notificationPacket.GetDataStream());
|
|
}
|
|
|
|
// Letzten X Nachrichten schicken
|
|
|
|
try
|
|
{
|
|
Monitor.Enter(_Lock);
|
|
|
|
DefaultHibernateSessionManager.CurrentTenant = dataPacket.Tenant;
|
|
|
|
|
|
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(_Lock);
|
|
}
|
|
|
|
break;
|
|
case DataIdentifier.Message:
|
|
if(responseByteCount == 0)
|
|
{
|
|
clientList.Remove(dataPacket.Socket);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
Monitor.Enter(_Lock);
|
|
|
|
DefaultHibernateSessionManager.CurrentTenant = dataPacket.Tenant;
|
|
|
|
var chatMessage = new ChatMessage
|
|
{
|
|
SenderPersonOid = dataPacket.SenderPersonOid,
|
|
ChatText = dataPacket.ChatMessage,
|
|
EmpfängerPersonOid = dataPacket.RecipientPersonOid,
|
|
Uhrzeit = dataPacket.MessageTimeStamp,
|
|
InsUser = dataPacket.ClientName
|
|
};
|
|
|
|
DAOFactory.GenericDAO.Insert(chatMessage);
|
|
|
|
if(dataPacket.RecipientPersonOid > 0 && clientList.ContainsValue(dataPacket.RecipientPersonOid))
|
|
{
|
|
var recipients = clientList.Where(w => w.Value.Equals(dataPacket.RecipientPersonOid));
|
|
|
|
foreach(var recipient in recipients)
|
|
{
|
|
recipient.Key.Send(dataPacket.GetDataStream());
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(_Lock);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case DataIdentifier.Logout:
|
|
|
|
clientList.Remove(dataPacket.Socket);
|
|
|
|
var notificationPacketLogout = new Packet(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, 0) {DataIdentifier = DataIdentifier.StatusNotificationLogout};
|
|
|
|
foreach (var client in clientList.Where(w => !w.Value.Equals(dataPacket.SenderPersonOid)))
|
|
{
|
|
client.Key.Send(notificationPacketLogout.GetDataStream());
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
WaitForClientData(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, dataPacket.RecipientPersonOid);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
var sender = dataPacket.Socket;
|
|
|
|
if(clientList.ContainsKey(sender))
|
|
{
|
|
clientList.Remove(sender);
|
|
sender.Close();
|
|
}
|
|
|
|
Debug.WriteLine("ChatServerException: " + e.Message);
|
|
}
|
|
}
|
|
}
|
|
} |