Асинхронный сервер не отвечает - C#
Формулировка задачи:
Добра.
Написал асинхронных сервер сервер и клиент для чата.
Порядок работы примерно таков:
Клиент подключается к серверу
Сервер получает запрос от клиента и отвечает ему.(если команда была непонятна отвечает "unknown command")
В то же время, на сервере хранится лист объектов класса User.
И когда приходит команда,например, написать сообщение в комнату, он определяет, в какой комнате находится сам юзер, достаёт всех юзеров с такой же комнаты и на их сокеты отправляет сообщение.
Всё просто.
Так же работает и юзер. Асинхронно отправляет команду, послу чего асинхронно ждёт ответ.
Ок.
У меня на ПК всё работает как часы, но как только я решил потестить на другом ПК - появилась неочевидная проблема.
Сначала сервер отвечает клиенту нормально, но потом, не понятно из-за чего, сервер перестаёт отвечать.
При чём клиент говорит, что сообщение отправил. Я приложил скриншот с исключением.
Так мы с другом перекинулись парой сообщений, а потом ему перестал отвечать сервер.
Подскажите, что в таких случаях делать?
Спасибо.
P.S. На всякий случай прикладываю код сервера и клиента.
Сервер:
class User { public string ID; public int room; public Socket sock; public User(string ID, int room, Socket sock) { this.ID = ID; this.sock = sock; this.room = room; } }
public class StateObject { // Client socket. public Socket workSocket = null; // Size of receive buffer. public const int BufferSize = 1024; // Receive buffer. public byte[] buffer = new byte[BufferSize]; // Received data string. public StringBuilder sb = new StringBuilder(); } public class AsynchronousSocketListener { // Thread signal. public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener() { } public static void StartListening(int PORT) { // Data buffer for incoming data. byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket. // The DNS name of the computer // running the listener is "host.contoso.com". IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("192.168.0.103"), PORT); // Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and listen for incoming connections. try { listener.Bind(localEndPoint); listener.Listen(100); while (true) { // Set the event to nonsignaled state. allDone.Reset(); // Start an asynchronous socket to listen for connections. Console.WriteLine("Waiting for a connection..."); listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); // Wait until a connection is made before continuing. allDone.WaitOne(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); } public static void AcceptCallback(IAsyncResult ar) { // Signal the main thread to continue. allDone.Set(); // Get the socket that handles the client request. Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Create the state object. 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; // Retrieve the state object and the handler socket // from the asynchronous state object. StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; try { // Read data from the client socket. int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { // There might be more data, so store the data received so far. state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead)); // Check for end-of-file tag. If it is not there, read // more data. content = state.sb.ToString(); if (content.IndexOf("<EOF>") > -1) { // All the data has been read from the client. Display it on the console. Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content); // Echo the data back to the client. //Send(handler, content); classUsersWorker.CommandReaction(content, handler); /*StateObject state1 = new StateObject(); state1.workSocket = handler; handler.BeginReceive(state1.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state1);*/ } else { // Not all data received. Get more. handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } } catch (Exception e) { try { Console.WriteLine(e.Message); handler.Shutdown(SocketShutdown.Both); handler.Close(); } catch { } } } public static void Send(Socket handler, String data) { // Convert the string data to byte data using UTF8 encoding. byte[] byteData = Encoding.UTF8.GetBytes(data + "<EOF>"); // Begin sending the data to the remote device. handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket handler = (Socket)ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {0} bytes to client.", bytesSent); //handler.Shutdown(SocketShutdown.Both); //handler.Close(); // Create the state object. StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } catch (Exception e) { Console.WriteLine(e.ToString()); } } } public class classUsersWorker { class User { public string ID; public int room; public Socket sock; public User(string ID, int room, Socket sock) { this.ID = ID; this.sock = sock; this.room = room; } } private static List<User> Users = new List<User>(); private static string UserIDGenerator() { int ID = new Random().Next(10000, 99999); foreach (User item in Users) { if (item.ID == ID.ToString()) { UserIDGenerator(); break; } } return ID.ToString(); } private static int RoomGenerator() { int room = new Random().Next(100, 999); foreach (User item in Users) { if (item.room == room) { UserIDGenerator(); break; } } return room; } private static User[] FindUsersInRoom(int room) { List<User> u = new List<User>(); foreach (User item in Users) if (item.room == room) u.Add(item); return u.ToArray(); } private static bool IsRoom(int room) { foreach (User item in Users) if (item.room == room) return true; return false; } private static bool RoomCreate(string command, Socket sock) { try { int room = RoomGenerator(); User u = new User(UserIDGenerator(), room, sock); Users.Add(u); AsynchronousSocketListener.Send(sock, "<room>" + room); return true; } catch (Exception) { return false; } } private static bool RoomConnect(string command, Socket sock) { string res = command.Replace("<room_connect>", "").Replace("<EOF>", ""); try { int room = Int32.Parse(res); if (IsRoom(room)) { User u = new User(UserIDGenerator(), room, sock); Users.Add(u); AsynchronousSocketListener.Send(sock, "<room>" + room); return true; } else { return false; } } catch (Exception) { return false; } } private static bool WriteToRoom(string command, Socket sock) { string[] StringSeparators = new string[] { "<write>", "<to>", "<EOF>" }; string[] result = command.Split(StringSeparators, StringSplitOptions.None); try { string msg = result[1]; int room = Int32.Parse(result[2]); User[] Roomers = FindUsersInRoom(room); bool access = false; foreach (User item in Roomers) if (item.sock == sock) access = true; if (access == true) { foreach (User item in Roomers) AsynchronousSocketListener.Send(item.sock, msg); return true; } else { return false; } } catch (Exception) { return false; } } public static bool CommandReaction(string command, Socket sock) { if (command.Contains("<room_create>")) if (RoomCreate(command, sock)) return true; if (command.Contains("<room_connect>")) if (RoomConnect(command, sock)) return true; if (command.Contains("<write>")) if (WriteToRoom(command, sock)) return true; AsynchronousSocketListener.Send(sock, "Unknown command<EOF>"); return false; } } class Program { public static int Main(String[] args) { AsynchronousSocketListener.StartListening(1100); return 0; } }
Решение задачи: «Асинхронный сервер не отвечает»
textual
Листинг программы
class Program { public static void Send(Socket handler, String data) { // Convert the string data to byte data using UTF8 encoding. byte[] byteData = Encoding.UTF8.GetBytes(data + "<EOF>"); // Begin sending the data to the remote device. handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket handler = (Socket)ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {0} bytes", bytesSent); //handler.Shutdown(SocketShutdown.Both); //handler.Close(); // Create the state object. StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } catch (Exception e) { Console.WriteLine(e.ToString()); Console.ReadLine(); } } public static void StartClient() { // Establish the remote endpoint for the socket. // This example uses port 11000 on the local computer. IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("92.249.117.132"), 1100); // Create a TCP/IP socket. Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); while (true) { // Data buffer for incoming data. byte[] bytes = new byte[1024]; try { if (!sender.Connected) { sender.Connect(remoteEP); Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString()); } string command = Console.ReadLine(); // Send the data through the socket. Send(sender, command); // Release the socket. // sender.Shutdown(SocketShutdown.Both); // sender.Close(); } catch (ArgumentNullException ane) { Console.WriteLine("ArgumentNullException : {0}", ane.ToString()); } catch (SocketException se) { Console.WriteLine("SocketException : {0}", se.ToString()); } catch (Exception e) { Console.WriteLine("Unexpected exception : {0}", e.ToString()); } } } public static void ReadCallback(IAsyncResult ar) { String content = String.Empty; // Retrieve the state object and the handler socket // from the asynchronous state object. StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; try { // Read data from the client socket. int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { // There might be more data, so store the data received so far. state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead)); // Check for end-of-file tag. If it is not there, read // more data. content = state.sb.ToString(); if (content.IndexOf("<EOF>") > -1) { // All the data has been read from the client. Display it on the console. Console.WriteLine(content.Replace("<EOF>", "")); StateObject state1 = new StateObject(); state1.workSocket = handler; handler.BeginReceive(state1.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state1); } else { // Not all data received. Get more. handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } } catch (Exception e) { Console.WriteLine(e); handler.Shutdown(SocketShutdown.Both); handler.Close(); } } static void Main(string[] args) { StartClient(); } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д