C#客户端/服务器聊天应用程序中的多线程问题
我有一个使用C#的TCP服务器/客户端聊天程序。该服务器接收来自客户的消息并重新发送到目标 当客户机连接到服务器时,服务器会为他创建一个新线程 我的问题是服务器只接收来自客户的一条消息,而不接收来自客户的任何新消息 当我进行调试时,我注意到服务器接收到消息并挂起客户端线程,但没有再次运行 服务器代码:C#客户端/服务器聊天应用程序中的多线程问题,c#,multithreading,tcplistener,C#,Multithreading,Tcplistener,我有一个使用C#的TCP服务器/客户端聊天程序。该服务器接收来自客户的消息并重新发送到目标 当客户机连接到服务器时,服务器会为他创建一个新线程 我的问题是服务器只接收来自客户的一条消息,而不接收来自客户的任何新消息 当我进行调试时,我注意到服务器接收到消息并挂起客户端线程,但没有再次运行 服务器代码: namespace server { public partial class Form1 : Form { private ArrayList alSockets; privat
namespace server
{
public partial class Form1 : Form
{
private ArrayList alSockets;
private delegate void UpdateLogCallback(string strMessage);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName());
textBox1.Text = "my ip is " + IPHost.AddressList[0].ToString();
alSockets = new ArrayList();
Thread thdListener = new Thread(new ThreadStart(listenerThread));
thdListener.Name = "thdListener";
thdListener.Start();
}
public void listenerThread()
{
TcpListener tcpc = new TcpListener(IPAddress.Any,6666);
tcpc.Start();
while (true)
{
Socket HndSoc = tcpc.AcceptSocket();
if (HndSoc.Connected)
{
string str2 = "\n" + HndSoc.RemoteEndPoint.ToString() + " connected";
this.Invoke(new UpdateLogCallback(this.update2),new object[] {str2});
lock (this)
{
alSockets.Add(HndSoc);
}
ThreadStart thdstHandler = new ThreadStart(handlerThread);
Thread thdHandler = new Thread(thdstHandler);
thdHandler.Name = "thdHandler";
thdHandler.Start();
}
else if(!HndSoc.Connected)
{
string str2 = "\n" + HndSoc.RemoteEndPoint.ToString() + " desconnected";
this.Invoke(new UpdateLogCallback(this.update2), new object[] { str2 });
}
}
}
public void handlerThread()
{
byte [] rx = new byte [1024];
Socket hanso = (Socket) alSockets[alSockets.Count-1];
NetworkStream ns = new NetworkStream(hanso);
// NetworkStream ns = hanso.
ns.Read(rx,0,rx.Length);
// textBox1.Text = "\n";
// textBox1.Text = Encoding.ASCII.GetString(rx);
string str = Encoding.ASCII.GetString(rx);
// update(str);
this.Invoke(new UpdateLogCallback(this.update), new object[] { str });
// ns.Close();
// hanso = null;
rx = new byte[1024];
ns.Read(rx, 0, rx.Length);
}
如果需要,这是客户端代码:
namespace simple_clint
{
public partial class Form1 : Form
{
byte[] tx = new byte[1024];
// IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"),6666);
TcpClient tcp1 = new TcpClient("127.0.0.1", 6666);
public Form1()
{
InitializeComponent();
}
private void send_Click(object sender, EventArgs e)
{
tx = Encoding.ASCII.GetBytes(textBox1.Text);
try
{
NetworkStream ns = tcp1.GetStream();
ns.Write(tx, 0, tx.Length);
// ns.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
多亏了卡哈克斯。我需要将循环添加到handlerThread() 新守则:
public void handlerThread()
{
byte[] rx = new byte[1024];
Socket hanso = (Socket)alSockets[alSockets.Count - 1];
while (true)
{
NetworkStream ns = new NetworkStream(hanso);
ns.Read(rx, 0, rx.Length);
string str = Encoding.ASCII.GetString(rx);
this.Invoke(new UpdateLogCallback(this.update), new object[] { str });
}
}
我从快速查看中删除了最后两行,似乎您需要在
handlerThread()
中添加一个循环。非常感谢您的帮助。它很有效。循环应位于此行之前:NetworkStream ns=新NetworkStream(hanso);我应该删除最后两行。所以,您的服务器代码不是线程安全的。在没有同步的情况下,您不能仅从多个线程修改和读取ArrayList
。您不能仅仅假设当处理程序线程开始读取套接字时,正确的仍然是列表中的最后一个。还有,为什么要使用ArrayList
?您是否被困在.NET1.1或其他版本上?只需使用列表
。并将接受的套接字直接传递给处理程序线程方法。异步I/O也可能是比多线程更好的选择-不需要浪费线程什么都不做。感谢您的注释我希望使用异步I/O,但没有看到关于它的好参考,如果您有一本好书或一篇文章,我希望给我。