2017-07-04 1 views
0

Ich versuche, ein Asynchronous Chat Server zu bauen, und das ist, was ich bisher habe:C# Asynchronous Chat Server

Server

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading; 

public class StateObject 
{ 
    public Socket workSocket = null; 
    public const int BufferSize = 1024; 
    public byte[] buffer = new byte[BufferSize]; 
    public StringBuilder sb = new StringBuilder(); 
} 

public class AsynchronousSocketListener 
{ 
public static ManualResetEvent allDone = new ManualResetEvent(false); 

public AsynchronousSocketListener() 
{ 
} 

public static void StartListening() 
{ 
    byte[] bytes = new Byte[1024]; 
    IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); 
    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); 
    Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); 

    try 
    { 
     listener.Bind(localEndPoint); 
     listener.Listen(100); 

     while (true) 
     { 
      allDone.Reset(); 
      Console.WriteLine("Waiting for a connection..."); 
      listener.BeginAccept(new AsyncCallback(AcceptCallback),listener); 
      allDone.WaitOne(); 
     } 

    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 

    Console.WriteLine("\nPress ENTER to continue..."); 
    Console.Read(); 

} 

public static void AcceptCallback(IAsyncResult ar) 
{ 
    allDone.Set(); 
    Socket listener = (Socket)ar.AsyncState; 
    Socket handler = listener.EndAccept(ar); 
    StateObject state = new StateObject(); 
    state.workSocket = handler; 
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(ReadCallback), state); 
} 

public static void ReadCallback(IAsyncResult ar) 
{ 
    String content = String.Empty; 
    StateObject state = (StateObject)ar.AsyncState; 
    Socket handler = state.workSocket; 
    int bytesRead = handler.EndReceive(ar); 

    if (bytesRead > 0) 
    { 
     state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 
     content = state.sb.ToString(); 
     if (content.IndexOf("<EOF>") > -1) 
     { 
      Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",content.Length, content); 
      Send(handler, content); 
     } 
     else 
     { 
      handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(ReadCallback), state); 
     } 
    } 
} 

private static void Send(Socket handler, String data) 
{ 
    byte[] byteData = Encoding.ASCII.GetBytes(data); 
    handler.BeginSend(byteData, 0, byteData.Length, 0,new AsyncCallback(SendCallback), handler); 
} 

private static void SendCallback(IAsyncResult ar) 
{ 
    try 
    { 
     Socket handler = (Socket)ar.AsyncState; 
     int bytesSent = handler.EndSend(ar); 
     Console.WriteLine("Sent {0} bytes to client.", bytesSent); 
     handler.Shutdown(SocketShutdown.Both); 
     handler.Close(); 

    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

public static int Main(String[] args) 
{ 
    StartListening(); 
    return 0; 
} 
} 

Kunde

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Threading; 
using System.Text; 

public class StateObject 
{ 
    public Socket workSocket = null; 
    public const int BufferSize = 256; 
    public byte[] buffer = new byte[BufferSize]; 
    public StringBuilder sb = new StringBuilder(); 
} 

public class AsynchronousClient 
{ 
    private const int port = 11000; 
    private static ManualResetEvent connectDone =new ManualResetEvent(false); 
    private static ManualResetEvent sendDone =new ManualResetEvent(false); 
    private static ManualResetEvent receiveDone =new ManualResetEvent(false); 
    private static String response = String.Empty; 
    static String username = ""; 
    static int a = 1; 

private static void StartClient() 
{ 
    try 
    { 
     Console.WriteLine("Username: "); 
     username = Console.ReadLine(); 

     while (a == 1) 
     { 
      IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); 
      IPEndPoint remoteEP = new IPEndPoint(ipAddress, port); 
      Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client); 
      connectDone.WaitOne(); 

      Console.WriteLine("Receiver: "); 
      String receiver = Console.ReadLine(); 
      Console.WriteLine("Message: "); 
      String message = Console.ReadLine(); 

      String Message = username + "[" + receiver + "[" + message + "<EOF>"; 
      Send(client, Message); 
      sendDone.WaitOne(); 
      Receive(client); 
      receiveDone.WaitOne(); 
      Console.WriteLine("Response received : {0}", response); 
     } 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

private static void ConnectCallback(IAsyncResult ar) 
{ 
    try 
    { 
     Socket client = (Socket)ar.AsyncState; 
     client.EndConnect(ar); 
     connectDone.Set(); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

private static void Receive(Socket client) 
{ 
    try 
    { 
     StateObject state = new StateObject(); 
     state.workSocket = client; 
     client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(ReceiveCallback), state); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

private static void ReceiveCallback(IAsyncResult ar) 
{ 
    try 
    { 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket client = state.workSocket; 
     int bytesRead = client.EndReceive(ar); 

     if (bytesRead > 0) 
     { 
      state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 
      client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(ReceiveCallback), state); 
     } 
     else 
     { 
      if (state.sb.Length > 1) 
      { 
       response = state.sb.ToString(); 
      } 
      receiveDone.Set(); 
     } 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

private static void Send(Socket client, String data) 
{ 
    byte[] byteData = Encoding.ASCII.GetBytes(data); 
    client.BeginSend(byteData, 0, byteData.Length, 0,new AsyncCallback(SendCallback), client); 
} 

private static void SendCallback(IAsyncResult ar) 
{ 
    try 
    { 
     Socket client = (Socket)ar.AsyncState; 
     int bytesSent = client.EndSend(ar); 
     Console.WriteLine("Sent {0} bytes to server.", bytesSent); 
     sendDone.Set(); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

public static int Main(String[] args) 
{ 
    StartClient(); 
    return 0; 
} 
} 

Ich bin in der Lage um Nachrichten an den Server zu senden und eine Antwort zurück zu bekommen, aber die Verbindung wird jedes Mal unterbrochen und ich muss sie wieder verbinden und so würde ich keine Nachrichten erhalten, nachdem ich eine gesendet habe. Ich suche nach einer Möglichkeit, meinen Client mit dem Server zu verbinden, Nachrichten auf beide Arten zu senden und die Verbindung manuell zu beenden. Außerdem suche ich nach einer Möglichkeit, Nachrichten von einem Client zu einem anderen zu senden und eine Nachricht an alle Clients zu senden, die mit dem Server verbunden sind.

Eine andere Frage, die ich habe, wie kann ich mehrere Ports einrichten und den Server alle Ports hören lassen? Ich wollte einen Port für den Login und einen Port für die Nachrichten öffnen.

+0

Sie schließen Ihren Socket im SendCallback auf dem Server, wenn Sie handler.ShutDown (...) ausführen; und handler.Close(); Ich denke, dass Sie den Sockel offen lassen müssen, bis die Verbindung von Ihnen beendet wird. https://msdn.microsoft.com/en-us/library/wahsac9k(v=vs.110).aspx – m4ttsson

Antwort

0

aber die Verbindung unterbrochen wird, jedes Mal,

weil Ihr schließen Sie es explizit in SendCallback

Socket handler = (Socket) ar.AsyncState; 
handler.Shutdown(SocketShutdown.Both); 
handler.Close(); 

Sie nennen handler.BeginReceive statt

+0

Ich bekomme keine Antwort vom Server, wenn ich Handler.BeginReceive stattdessen aufrufen. –

1

ich für eine freu Möglichkeit, meinen Client mit dem Server zu verbinden, Nachrichten auf beide Arten zu senden und den c zu stoppen Verbindung manuell.

Das Schließen der Verbindung kann durch Hinzufügen eines Verbindungsaufrufs nach der Schleife erfolgen: client.Disconnect(false). Nach einer Ausgangsbedingung beenden Sie einfach die Schleife.

Es wäre vorzuziehen, den Client in einer using Anweisung zu erstellen, auf diese Weise wird es automatisch entsorgt.

+0

Können Sie ein Beispiel für die using-Anweisung geben? –

+0

Werfen Sie einen Blick hier: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement –