C# 多客户端异步聊天错误
我用C#中的异步套接字制作了一个小型聊天应用程序 聊天是针对多个客户端进行的 问题是:当我在环回IP(127.0.0.1)上打开服务器并在计算机上打开几个客户端时,我成功地在它们之间发送了消息 但是,当我在我的计算机(127.0.0.1)上打开服务器,并在另一台计算机上打开客户端时,通信失败。当我试图从另一台计算机连接到服务器时,客户端崩溃(因为它无法连接) 代码: 服务器:C# 多客户端异步聊天错误,c#,.net,networking,communication,C#,.net,Networking,Communication,我用C#中的异步套接字制作了一个小型聊天应用程序 聊天是针对多个客户端进行的 问题是:当我在环回IP(127.0.0.1)上打开服务器并在计算机上打开几个客户端时,我成功地在它们之间发送了消息 但是,当我在我的计算机(127.0.0.1)上打开服务器,并在另一台计算机上打开客户端时,通信失败。当我试图从另一台计算机连接到服务器时,客户端崩溃(因为它无法连接) 代码: 服务器: namespace ServerForm { public partial class Form1 : Form
namespace ServerForm
{
public partial class Form1 : Form
{
private Socket _serverSocket;
private readonly List<Socket> _clientSockets = new List<Socket>();
private const int _BUFFER_SIZE = 2048;
private const int _PORT = 513;
private readonly byte[] _buffer = new byte[_BUFFER_SIZE];
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
SetupServer();
}
private void SetupServer()
{
//Console.WriteLine("Setting up server...");
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(0, 1234));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback, null);
//Console.WriteLine("Server setup complete");
}
private void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
private void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot 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("Client connected, waiting for request...");
_serverSocket.BeginAccept(AcceptCallback, null);
}
private void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
//Console.WriteLine("Client forcefully disconnected");
current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
_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() == "get time") // Client requested time
{
//Console.WriteLine("Text is a get time request");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
for (int i = 0; i < _clientSockets.Count; i++) _clientSockets[i].Send(Encoding.ASCII.GetBytes(text));
//Console.WriteLine("Time sent to client");
}
else if (text.ToLower() == "exit") // Client wants to exit gracefully
{
// Always Shutdown before closing
current.Shutdown(SocketShutdown.Both);
current.Close();
_clientSockets.Remove(current);
Console.WriteLine("Client disconnected");
return;
}
else
{
//Console.WriteLine("Text is an invalid request");
byte[] data = Encoding.ASCII.GetBytes("Invalid request");
for (int i = 0; i < _clientSockets.Count; i++) _clientSockets[i].Send(Encoding.ASCII.GetBytes(text));
//Console.WriteLine("Warning Sent");
}
current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
}
namespace ChatForm
{
public partial class Form1 : Form
{
private readonly Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private const int _PORT = 1234;
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void label1_Click(object sender, EventArgs e)
{
}
private void connect_Click(object sender, EventArgs e)
{
if (name.Text == "" || s_ip.Text == "") MessageBox.Show("Fields cannot be empty.");
else ConnectToServer();
}
private void ConnectToServer()
{
IPAddress connection = IPAddress.Parse(s_ip.Text);
IPAddress server = connection;
int attempts = 1;
while (!_clientSocket.Connected)
{
try
{
_clientSocket.Connect(connection, _PORT);
}
catch (SocketException) // it crashes if it reaches here
{
}
}
MessageBox.Show("Successfully connected to server");
RequestLoop();
}
private void RequestLoop()
{
Thread t1 = new Thread(ReceiveResponse);
t1.Start();
}
/// <summary>
/// Close socket and exit app
/// </summary>
private void Exit()
{
SendString("exit");
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
Environment.Exit(0);
}
private void SendRequest()
{
string request = "[" + name.Text + "] " + text.Text + "\n";
SendString(request);
if (request.ToLower() == "exit")
{
Exit();
}
}
/// <summary>
/// Sends a string to the server with ASCII encoding
/// </summary>
private void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
//MessageBox.Show("Sent");
}
private void ReceiveResponse()
{
while (true)
{
var buffer = new byte[2048];
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);
display.AppendText(text);
if (text.Contains("MessageBox!"))
{
MessageBox.Show(text.Split('!')[1]);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
SendRequest();
text.Text = "";
}
}
}
namespace服务器表单
{
公共部分类Form1:Form
{
专用套接字_serverSocket;
私有只读列表_clientSockets=new List();
私有常量int_BUFFER_SIZE=2048;
专用const int_PORT=513;
专用只读字节[]\u buffer=新字节[\u buffer\u SIZE];
公共表格1()
{
初始化组件();
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
按钮1.启用=错误;
SetupServer();
}
私有void SetupServer()
{
//Console.WriteLine(“设置服务器…”);
_serverSocket=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp);
_Bind(新的IPEndPoint(01234));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback,null);
//Console.WriteLine(“服务器设置完成”);
}
私有void CloseAllSockets()
{
foreach(客户端插座中的插座)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
私有void AcceptCallback(IAsyncResult AR)
{
插座;
尝试
{
套接字=_serverSocket.EndAccept(AR);
}
catch(ObjectDisposedException)//我似乎无法避免(在正确关闭套接字时退出时)
{
返回;
}
_clientSockets.Add(socket);
socket.BeginReceive(_buffer,0,_buffer_SIZE,SocketFlags.None,ReceiveCallback,socket);
//WriteLine(“客户端已连接,正在等待请求…”);
_serverSocket.BeginAccept(AcceptCallback,null);
}
私有void ReceiveCallback(IAsyncResult AR)
{
插座电流=(插座)AR.AsyncState;
收到整数;
尝试
{
已接收=当前的EndReceive(AR);
}
捕获(SocketException)
{
//Console.WriteLine(“客户端强制断开”);
current.Close();//不要关机,因为套接字可能已被释放,并且其连接可能已断开
_clientSockets.移除(当前);
返回;
}
字节[]recBuf=新字节[已接收];
复制(_buffer,recBuf,received);
字符串文本=Encoding.ASCII.GetString(recBuf);
//Console.WriteLine(“接收到的文本:+文本”);
if(text.ToLower()=“获取时间”)//客户端请求的时间
{
//WriteLine(“文本是获取时间请求”);
byte[]data=Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
对于(int i=0;i<_clientSockets.Count;i++)_clientSockets[i].Send(Encoding.ASCII.GetBytes(text));
//Console.WriteLine(“发送给客户的时间”);
}
else if(text.ToLower()=“exit”)//客户端希望正常退出
{
//总是在关闭前关闭
电流关闭(SocketShutdown.Both);
current.Close();
_clientSockets.移除(当前);
Console.WriteLine(“客户端断开”);
返回;
}
其他的
{
//Console.WriteLine(“文本是无效的请求”);
byte[]data=Encoding.ASCII.GetBytes(“无效请求”);
对于(int i=0;i<_clientSockets.Count;i++)_clientSockets[i].Send(Encoding.ASCII.GetBytes(text));
//控制台。写入线(“已发送警告”);
}
current.BeginReceive(_buffer,0,_buffer,大小,SocketFlags.None,ReceiveCallback,current);
}
}
}
客户端:
namespace ServerForm
{
public partial class Form1 : Form
{
private Socket _serverSocket;
private readonly List<Socket> _clientSockets = new List<Socket>();
private const int _BUFFER_SIZE = 2048;
private const int _PORT = 513;
private readonly byte[] _buffer = new byte[_BUFFER_SIZE];
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
SetupServer();
}
private void SetupServer()
{
//Console.WriteLine("Setting up server...");
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(0, 1234));
_serverSocket.Listen(5);
_serverSocket.BeginAccept(AcceptCallback, null);
//Console.WriteLine("Server setup complete");
}
private void CloseAllSockets()
{
foreach (Socket socket in _clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
_serverSocket.Close();
}
private void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = _serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot 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("Client connected, waiting for request...");
_serverSocket.BeginAccept(AcceptCallback, null);
}
private void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
//Console.WriteLine("Client forcefully disconnected");
current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
_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() == "get time") // Client requested time
{
//Console.WriteLine("Text is a get time request");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
for (int i = 0; i < _clientSockets.Count; i++) _clientSockets[i].Send(Encoding.ASCII.GetBytes(text));
//Console.WriteLine("Time sent to client");
}
else if (text.ToLower() == "exit") // Client wants to exit gracefully
{
// Always Shutdown before closing
current.Shutdown(SocketShutdown.Both);
current.Close();
_clientSockets.Remove(current);
Console.WriteLine("Client disconnected");
return;
}
else
{
//Console.WriteLine("Text is an invalid request");
byte[] data = Encoding.ASCII.GetBytes("Invalid request");
for (int i = 0; i < _clientSockets.Count; i++) _clientSockets[i].Send(Encoding.ASCII.GetBytes(text));
//Console.WriteLine("Warning Sent");
}
current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
}
namespace ChatForm
{
public partial class Form1 : Form
{
private readonly Socket _clientSocket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private const int _PORT = 1234;
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void label1_Click(object sender, EventArgs e)
{
}
private void connect_Click(object sender, EventArgs e)
{
if (name.Text == "" || s_ip.Text == "") MessageBox.Show("Fields cannot be empty.");
else ConnectToServer();
}
private void ConnectToServer()
{
IPAddress connection = IPAddress.Parse(s_ip.Text);
IPAddress server = connection;
int attempts = 1;
while (!_clientSocket.Connected)
{
try
{
_clientSocket.Connect(connection, _PORT);
}
catch (SocketException) // it crashes if it reaches here
{
}
}
MessageBox.Show("Successfully connected to server");
RequestLoop();
}
private void RequestLoop()
{
Thread t1 = new Thread(ReceiveResponse);
t1.Start();
}
/// <summary>
/// Close socket and exit app
/// </summary>
private void Exit()
{
SendString("exit");
_clientSocket.Shutdown(SocketShutdown.Both);
_clientSocket.Close();
Environment.Exit(0);
}
private void SendRequest()
{
string request = "[" + name.Text + "] " + text.Text + "\n";
SendString(request);
if (request.ToLower() == "exit")
{
Exit();
}
}
/// <summary>
/// Sends a string to the server with ASCII encoding
/// </summary>
private void SendString(string text)
{
byte[] buffer = Encoding.ASCII.GetBytes(text);
_clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
//MessageBox.Show("Sent");
}
private void ReceiveResponse()
{
while (true)
{
var buffer = new byte[2048];
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);
display.AppendText(text);
if (text.Contains("MessageBox!"))
{
MessageBox.Show(text.Split('!')[1]);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
SendRequest();
text.Text = "";
}
}
}
名称空间格式
{
公共部分类Form1:Form
{
专用只读套接字_clientSocket=新套接字
(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
专用const int_PORT=1234;
公共表格1()
{
初始化组件();
Control.CheckForIllegalCrossThreadCalls=false;
}
私有无效标签1_单击(对象发送方,事件参数e)
{
}
私有void connect\u单击(对象发送方,事件参数e)
{
if(name.Text==“”| | s|u ip.Text==“”)MessageBox.Show(“字段不能为空”);
else ConnectToServer();
}
私有void ConnectToServer()
{
IPAddress连接=IPAddress.Parse(s_ip.Text);
IP地址服务器=连接;
int=1;
while(!\u clientSocket.Connected)
{
尝试
{
_clientSocket.Connect(连接,_端口);
}
catch(SocketException)//如果到达此处,它将崩溃
{
}
}
MessageBox.Show(“已成功连接到服务器”);
RequestLoop();
}
私有void RequestLoop()
{
线程t1=新线程(接收方响应);
t1.Start();