Асинхронный сервер не отвечает - 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();
}
}