我最近有玩Socket 的多线程的问题
但我的程序逻辑有些问题,我的Server端可以接受多个Client端的连接,并且都能接受他们所发送过来的数据,但只要其中一个Client端断开后,服务器端就接受不了其他Client端发送过来的数据,我知道我的逻辑有问题(后面是我的Server端的部分代码),但我不知道怎么写?请各位大侠指教!谢谢
然后我的Server端需要要向指定的Client端发送数据,这么我怎么才能做的到?(向指定的Client发送指定信息), 请大侠们指教一下,最好有代码,谢谢!以下是我Server端的部分代码: //开启线程
public void StartThread()
{ // ClientNumber++;
ServerThread = new Thread(new ThreadStart(RecieveAccept));//将接受客户端连接的方法委托给线程 ServerThread.Start(); CheckForIllegalCrossThreadCalls = false;//不捕获对错误线程的调用 this.SetText("服务于" + DateTime.Now.ToString() + "开始运行");
} //接受客户端连接的方法和接收数据
private void RecieveAccept()
{
while(true)
{
//ClientNumber++; ServerSocket.Listen(10);//开始监听,并且挂起数为10 ClientSocket[ClientNumber] = ServerSocket.Accept(); this.StartThread();
ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
this.SetText(ClientSocket[ClientNumber].RemoteEndPoint.ToString()); //this.StartReceiveMsgThread(); while (m == 1)
{
try
{
i = ClientSocket[ClientNumber].Receive(msgbuffer);
//ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
}
catch (Exception)
{ MessageBox.Show("有一客户端断开", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
//return;
break;
}
msg = Encoding.Unicode.GetString(msgbuffer, 0, msgbuffer.Length);
this.SetText(msg); System.Array.Clear(msgbuffer, 0, msgbuffer.Length); if (msg.Trim() == "stop")
{
m = 0;
} }
//this.SetText(msgbuffer.ToString());
ClientNumber++; }
}
但我的程序逻辑有些问题,我的Server端可以接受多个Client端的连接,并且都能接受他们所发送过来的数据,但只要其中一个Client端断开后,服务器端就接受不了其他Client端发送过来的数据,我知道我的逻辑有问题(后面是我的Server端的部分代码),但我不知道怎么写?请各位大侠指教!谢谢
然后我的Server端需要要向指定的Client端发送数据,这么我怎么才能做的到?(向指定的Client发送指定信息), 请大侠们指教一下,最好有代码,谢谢!以下是我Server端的部分代码: //开启线程
public void StartThread()
{ // ClientNumber++;
ServerThread = new Thread(new ThreadStart(RecieveAccept));//将接受客户端连接的方法委托给线程 ServerThread.Start(); CheckForIllegalCrossThreadCalls = false;//不捕获对错误线程的调用 this.SetText("服务于" + DateTime.Now.ToString() + "开始运行");
} //接受客户端连接的方法和接收数据
private void RecieveAccept()
{
while(true)
{
//ClientNumber++; ServerSocket.Listen(10);//开始监听,并且挂起数为10 ClientSocket[ClientNumber] = ServerSocket.Accept(); this.StartThread();
ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
this.SetText(ClientSocket[ClientNumber].RemoteEndPoint.ToString()); //this.StartReceiveMsgThread(); while (m == 1)
{
try
{
i = ClientSocket[ClientNumber].Receive(msgbuffer);
//ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
}
catch (Exception)
{ MessageBox.Show("有一客户端断开", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
//return;
break;
}
msg = Encoding.Unicode.GetString(msgbuffer, 0, msgbuffer.Length);
this.SetText(msg); System.Array.Clear(msgbuffer, 0, msgbuffer.Length); if (msg.Trim() == "stop")
{
m = 0;
} }
//this.SetText(msgbuffer.ToString());
ClientNumber++; }
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;namespace AsyncTcpServer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
setComboBoxCallback = new SetComboBoxCallback(SetComboBox);
setListBoxCallback = new SetListBoxCallback(SetListBox);
setRichTextBoxCallback = new SetRichTextBoxCallback(setRichText);
removeComboBoxItemsCallback = new RemoveComboBoxItemsCallback(RemoveComboBoxItems);
}
private bool isExit = false;
System.Collections.ArrayList clientList = new System.Collections.ArrayList();//保存连接所有的客服端
TcpListener listener;//监听客服端连接
private delegate void SetListBoxCallback(string str);
private SetListBoxCallback setListBoxCallback;
private delegate void SetRichTextBoxCallback(string str);
private SetRichTextBoxCallback setRichTextBoxCallback;
private delegate void SetComboBoxCallback(string str);
private SetComboBoxCallback setComboBoxCallback;
private delegate void RemoveComboBoxItemsCallback(ReadWriteObject readWriteObject);
private RemoveComboBoxItemsCallback removeComboBoxItemsCallback; private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);//用于线程同步,初始为非终止状态,使用手动设置方式
private void RemoveComboBoxItems(ReadWriteObject readWriteObject)
{
int index = clientList.IndexOf(readWriteObject);
comboBox1.Items.RemoveAt(index);
} private void SetListBox(string str)
{
listBox1.Items.Add(str);
listBox1.SelectedIndex = listBox1.Items.Count - 1;
listBox1.ClearSelected();
} private void setRichText(string str)
{
receive_text.AppendText(str);
} private void SetComboBox(object obj)
{
comboBox1.Items.Add(obj);
} private void AcceptConnect()
{
IPAddress[] ip = Dns.GetHostAddresses(Dns.GetHostName());//获取本机IP地址
listener = new TcpListener(ip[0], 51888);//创建监听
listener.Start();//启动监听
while(isExit==false)//循环监听客服端发过来的请求
{
try
{
allDone.Reset();//将事件设置为非终止状态,不让操作系统发出信号
AsyncCallback callback = new AsyncCallback(AcceptTcpClient);//引用在异步操作完成时调用的方法
listBox1.Invoke(setListBoxCallback, "开始等待客户连接");
listener.BeginAcceptTcpClient(callback, listener);//开始一个异步操作接收传来的连接尝试
allDone.WaitOne();//阻塞当前线程,直到收到客服端的连接信号
}
catch (Exception ex)
{
listBox1.Invoke(setListBoxCallback, ex.Message);
break;
}
}
} private void AcceptTcpClient(IAsyncResult ar)//ar 异步操作状态
{ //是由 listener.BeginAcceptTcpClient(callback, listener)传递过来的
try
{
allDone.Set();//将事件状态设置为终止,让等待的一个或者多个线程继续
TcpListener myListener = (TcpListener)ar.AsyncState;
TcpClient client = myListener.EndAcceptTcpClient(ar);//异步接收传入的连接,并创建新的Tcplient对象处理远程主机通信
listBox1.Invoke(setListBoxCallback, "已接受客服连接:" + client.Client.RemoteEndPoint);
comboBox1.Invoke(setComboBoxCallback, client.Client.RemoteEndPoint.ToString());
ReadWriteObject readWriteObject = new ReadWriteObject(client);
clientList.Add(readWriteObject);
SendString(readWriteObject, "服务器已经接受连接,请通话!");
//开始异步读取
readWriteObject.netStream.BeginRead(readWriteObject.readBytes, 0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
}
catch(Exception ex)
{
listBox1.Invoke(setListBoxCallback, ex.Message);
return;
}
} private void ReadCallback(IAsyncResult ar)
{
try
{
ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
int count = readWriteObject.netStream.EndRead(ar);
receive_text.Invoke(setRichTextBoxCallback, string.Format("[来自{0}]{1}", readWriteObject.client.Client.RemoteEndPoint, System.Text.Encoding.UTF8.GetString(readWriteObject.readBytes, 0, count)));
if(isExit==false)
{
readWriteObject.InitReadArray();
readWriteObject.netStream.BeginRead(readWriteObject.readBytes, 0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
}
}
catch(Exception ex)
{
listBox1.Invoke(setListBoxCallback, ex.Message);
}
}
private void SendString(ReadWriteObject readWriteObject,string str)
{
try
{
readWriteObject.writeBytes = System.Text.Encoding.UTF8.GetBytes(str + "\r\n");
//开始向流异步写入数据
readWriteObject.netStream.BeginWrite(readWriteObject.writeBytes, 0, readWriteObject.writeBytes.Length, new AsyncCallback(SendCallback), readWriteObject);
readWriteObject.netStream.Flush();//刷新流中的数据
listBox1.Invoke(setListBoxCallback, string.Format("向{0}发送:{1}", readWriteObject.client.Client.RemoteEndPoint, str));
}
catch(Exception ex)
{
listBox1.Invoke(setListBoxCallback, ex.Message);
}
} private void SendCallback(IAsyncResult ar)
{
ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
try
{
readWriteObject.netStream.EndWrite(ar);//结束异步流的写入
}
catch(Exception ex)
{
listBox1.Invoke(setListBoxCallback, ex.Message);
comboBox1.Invoke(removeComboBoxItemsCallback, readWriteObject);
}
}
private void start_btn_Click(object sender, EventArgs e)
{
ThreadStart ts = new ThreadStart(AcceptConnect);//监听客服端的请求
Thread myThread = new Thread(ts);
myThread.Start();
start_btn.Enabled = false;
stop_btn.Enabled = true;
} private void stop_btn_Click(object sender, EventArgs e)
{
isExit = true;
allDone.Set();
start_btn.Enabled = true;
stop_btn.Enabled = false;
} private void send_btn_Click(object sender, EventArgs e)
{
int index = comboBox1.SelectedIndex;
if(index==-1)
{
MessageBox.Show("请先选择接受方,然后在发送");
}
else
{
ReadWriteObject obj = (ReadWriteObject)clientList[index];
SendString(obj, send_text.Text);
send_text.Clear();
}
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
stop_btn_Click(null, null);
}
}
}
源代码和实现说明:
http://www.codeproject.com/KB/IP/AsyncSocketServerandClien.aspx效果图:
一个Receive线程。
你少了一个Listen线程。
ClientSocket[ClientNumber].BeginReceive(msgbuffer, 0, msgbuffer.Length, 0, new
AsyncCallback(RecieveCallBack), ClientSocket[ClientNumber]);
接收连接请求用一个独立的线程处理,针对每一个连接请求创建新工作线程,
监听请求如下面的模式: private void RecieveAccept()
{
while(true)
{
//ClientNumber++; ServerSocket.Listen(10);//开始监听,并且挂起数为10 ClientSocket[ClientNumber] = ServerSocket.Accept(); this.StartThread();//这里同时将套接字以参数方式传递给工作线程
......
}
http://msdn.microsoft.com/zh-cn/library/w89fhyex.aspx
怎么样把Socket传给线程啊?
你前面已经BEGINReceive了,那么ENDReceive的逻辑就应该在BEGINRECEIVE的异步回调函数里写啊。
而你后面又跟了个RECEIVE这个是阻塞的啊。没有数据来,就一直阻塞到的。你后面的连接怎么进得来呢?