Я пытаюсь сделать небольшой сервер и мульти-клиентское программное обеспечение. Я использую сервер в качестве консольного приложения и клиент в качестве клиента WPF. Мне удалось отправить сообщения через, но я не могу потоковое подключение подключенных пользователей в моем списке. Я хочу показать подключенных пользователей во всех клиентах. Это мой код. Так как я пытался использовать MessageCallBack, я подключил свой клиент и немедленно отключил его. Что я делаю не так?
СЕРВЕР
namespace SocketApp
{
class Server
{
private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static readonly EndPoint epLocal, epRemote;
private static readonly List<Socket> clientSockets = new List<Socket>();
private const int BUFFER_SIZE = 2048;
private const int PORT = 100;
private static readonly byte[] buffer = new byte[BUFFER_SIZE];
static void Main(string[] args)
{
Console.Title = "Server";
SetupServer();
Console.ReadLine(); // When we press enter close everything
CloseAllSockets();
}
private static void SetupServer()
{
Console.WriteLine("Setting up server...");
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
serverSocket.Listen(0);
serverSocket.BeginAccept(AcceptCallback, null);
Console.WriteLine("Server setup complete");
}
/// <summary>
/// Close all connected client (we do not need to shutdown the server socket as its connections
/// are already closed with the clients).
/// </summary>
private static void CloseAllSockets()
{
foreach (Socket socket in clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
serverSocket.Close();
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I can not seem to avoid this (on exit when properly closing sockets)
{
return;
}
clientSockets.Add(socket);
socket.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("{0}", socket.RemoteEndPoint + " connected...");
foreach (object obj in clientSockets)
{
Socket socket2 = (Socket)obj;
string message = socket2.RemoteEndPoint.ToString();
byte[] data = Encoding.ASCII.GetBytes(message);
socket2.Send(data);
}
serverSocket.BeginAccept(AcceptCallback, null);
}
private static void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
// Don't shutdown because the socket may be disposed and its disconnected anyway.
current.Close();
clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
Console.WriteLine("Received Text: " + text);
if (text.ToLower() == "meeting") // Client requested time
{
foreach (object obj in clientSockets)
{
string message = "meeting";
byte[] data = Encoding.ASCII.GetBytes(message);
Socket socket = (Socket)obj;
socket.Send(data);
Console.WriteLine("Meeting invite sent to " + socket.RemoteEndPoint);
}
}
else if (text.ToLower() == "exit") // Client wants to exit gracefully
{
// Always Shutdown before closing
Console.WriteLine(current.RemoteEndPoint + " disconnected");
current.Shutdown(SocketShutdown.Both);
current.Close();
clientSockets.Remove(current);
return;
}
else if (text.ToLower() == "offline") // Client requested time
{
foreach (object obj in clientSockets)
{
string message = "offline";
byte[] data = Encoding.ASCII.GetBytes(message);
Socket socket = (Socket)obj;
socket.Send(data);
Console.WriteLine("Offline user: " + socket.RemoteEndPoint);
}
}
else
{
Console.WriteLine("Invalid request");
byte[] data = Encoding.ASCII.GetBytes("Invalid request");
current.Send(data);
Console.WriteLine("Warning Sent");
}
current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
}
КЛИЕНТ WPF
namespace Client
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
EndPoint epRemote;
private const int PORT = 100;
private byte[] buffer;
private string message { get; set; }
public string serverMessage { get; set; }
public MainWindow()
{
InitializeComponent();
ConnectToServer();
UpdateControls();
connectedUsers();
}
private void connectedUsers()
{
//Listen to the ports
byte[] buffer = new byte[1500];
ClientSocket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
}
private void UpdateControls()
{
lblMessage.Content = message;
//txtFromServer.Text = serverMessage;
}
private void ConnectToServer()
{
int attempts = 0;
while (!ClientSocket.Connected)
{
try
{
attempts++;
//lblMessage.Text = "Connection attempt " + attempts;
// Change IPAddress.Loopback to a remote IP to connect to a remote host.
//ClientSocket.Connect(IPAddress.Loopback, PORT);
ClientSocket.Connect("localhost", PORT);
}
catch (SocketException ex)
{
MessageBox.Show(ex.Message + Environment.NewLine + "Connection attempt " + attempts);
}
}
message = "Connected";
var buffer = new byte[2048];
try
{
if (buffer.ToString().Length == 2048) return;
int received = ClientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
list_Users.Items.Add(text);
//txt_ConnectedUsers.Text += text + System.Environment.NewLine;
//MessageBox.Show(text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
private void RequestLoop()
{
while (true)
{
SendRequest("");
ReceiveResponse();
}
}
private void SendRequest(string text)
{
string request = text;
SendString(request);
if (request.ToLower() == "exit")
{
Exit();
}
}
/// <summary>
/// Sends a string to the server with ASCII encoding.
/// </summary>
private void SendString(string text)
{
try
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
ClientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if(txt_TextMessage.Text == "")
{
UpdateControls();
return;
}
else
{
SendRequest(txt_TextMessage.Text);
ReceiveResponse();
UpdateControls();
}
}
private void Exit()
{
SendString("exit"); // Tell the server we are exiting
ClientSocket.Shutdown(SocketShutdown.Both);
ClientSocket.Close();
Environment.Exit(0);
}
public void ReceiveResponse()
{
var buffer = new byte[2048];
try
{
if (buffer.ToString().Length == 2048) return;
int received = ClientSocket.Receive(buffer, SocketFlags.None);
if (received == 0) return;
var data = new byte[received];
Array.Copy(buffer, data, received);
string text = Encoding.ASCII.GetString(data);
txt_TextFromServer.Text += text + System.Environment.NewLine;
//MessageBox.Show(text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
private void MessageCallBack(IAsyncResult aResult)
{
try
{
this.Dispatcher.Invoke(() =>
{
int size = ClientSocket.EndReceiveFrom(aResult, ref epRemote);
if (size > 0)
{
byte[] receiveData = new byte[1500];
receiveData = (byte[])aResult.AsyncState;
ASCIIEncoding eEncoding = new ASCIIEncoding();
string receivedMessage = eEncoding.GetString(receiveData);
//Populate connected users
list_Users.Items.Add(receivedMessage);
}
byte[] buffer = new byte[1500];
ClientSocket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
});
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Exit();
}
}
}