Socket线程池的问题!!!!!!!!

heidong2002 2009-09-14 01:12:04
private Thread qSerTh;
private TcpListener qTcpListener = null;

private void button1_Click(object sender, EventArgs e)
{
try
{
qSerTh = new Thread(new ThreadStart(ServerIng));
qSerTh.IsBackground = true;
qSerTh.Start();
}
catch
{
MessageBox.Show("线程启动错误");
}
}

private void ServerIng()
{
try
{
qTcpListener = new TcpListener(IPAddress.Parse("192.168.0.1"), Convert.ToInt16(11000));
qTcpListener.Start();
string msg = "";

while (true)
{
Socket QS;
QS = qTcpListener.AcceptSocket();
string RemoteEndPoint = QS.RemoteEndPoint.ToString();
IPAddress remoteip = ((IPEndPoint)QS.RemoteEndPoint).Address;
int remoteport = ((IPEndPoint)QS.RemoteEndPoint).Port;
Byte[] Stream = new Byte[1024];
QS.Receive(Stream);
string save = System.Text.Encoding.UTF8.GetString(Stream);
string[] ss = save.Split('|');
switch (ss[0])
{
case "Login"://验证用户登陆消息
..........
break;
default://发送错误参数
break;
}
QS.Close();
}
}
catch { }
finally
{
qTcpListener.Stop();
}
}
//-------------------------------------------------------------------------------------
这段程序启动了一个线程在后台监听客户端的连接。
现在的问题是:连接后要交换很多数据,比较费时,很多客户端同时连接可能影响服务器的效率。
这时,我想使用线程池,但不知如何写,请高手指点。
另外,有人说BeginXXX方法和EndXXX方法会利用c#内置的线程池,且性能较高,是这样吗?这种方法又如何写呢?
...全文
751 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
wenbin 2009-09-15
  • 打赏
  • 举报
回复
QS.BeginRecieve方法,然后这个方法会回调另一个方法,
就是RecieveCallBack,这里已经接收到数据,处理你的数据
处理数据时小心TCP的边界问题。
再递归调用BeginRecieve方法。

若是这个连接以后还要用的话,那么就不要断开,建立一个用户管理集合


东西还是比较多的。
heidong2002 2009-09-15
  • 打赏
  • 举报
回复
我想用线程池是因为有些连接用于传送文件,这时候应比较费时,如果多几个用户传文件,也许有些用户的登录会受到影响,所以想为每个连接设立单独的线程,考虑到系统开销,又想用线程池.
我上面的程序可正常运行,但不知用线程池或BeginXXX方法和EndXXX方法怎么改,Socket方面是个新手,请指教.能帮我改下代码更是感激不尽,谢谢!!!
qldsrx 2009-09-15
  • 打赏
  • 举报
回复
这是客户端程序:

public partial class Form1 : Form
{
TcpClient tcp;
IPEndPoint remoteEP;
FileStream fs;

public Form1()
{
InitializeComponent();
tcp = new TcpClient();
tcp.Client.ReceiveTimeout = 2000;
remoteEP = new IPEndPoint(IPAddress.Parse("192.168.26.98"), 12345);
}

private void button1_Click(object sender, EventArgs e)
{
if (remoteEP != null)
{
tcp.Client.BeginConnect(remoteEP, callback, tcp.Client);
}
}

void callback(IAsyncResult ar)
{
Socket handler = (Socket)ar.AsyncState;
try
{
handler.EndConnect(ar);
}
catch (Exception ex)
{
MessageBoxShow(ex.Message);
}

try
{
byte[] bytes = Encoding.UTF8.GetBytes("Move.txt");
handler.Send(bytes);
}
catch (Exception ex)
{
MessageBoxShow(ex.Message);
}

try
{
byte[] receive = new byte[1024];
int count = 0;
fs = new FileStream("d:\\Move.txt", FileMode.OpenOrCreate);
//fs.Position = 0;
while (true)
{
count = handler.Receive(receive);
if (count > 0)
{
fs.Write(receive, 0, count);
}
else//注意,如果服务器端文件发送完毕后直接断开连接,则会进入这里。
{
fs.Flush();
fs.Close();
handler.Close();
MessageBoxShow("连接断开,可能是文件已经传输完毕。");
break;
}
}
}
catch (Exception ex)
{
if (fs != null)
{
fs.Flush();
fs.Close();
handler.Close();
}
MessageBox.Show(ex.Message);
}
}

void MessageBoxShow(string msg)
{
if (this.InvokeRequired)
{
Action showmsg = () => MessageBox.Show(msg);
this.Invoke(showmsg);
}
else
{
MessageBox.Show(msg);
}
}
}


另外服务器端程序最好在“MessageBoxShow("发送完毕");”将socket连接关闭,因为我这里文件传完后socket就不使用了,忘了在那上面的代码里添加了。

if (File.Exists(file))
{
handler.SendFile(file);
handler.Close();
MessageBoxShow("发送完毕");
}

qldsrx 2009-09-15
  • 打赏
  • 举报
回复
给你一个我写的代码,异步接收,同步收发(服务端程序)。

public partial class Form1 : Form
{
TcpListener tcplistener;
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 12345);
string basePath = "D:\\";

public static ManualResetEvent allDone = new ManualResetEvent(false);

public Form1()
{
InitializeComponent();

tcplistener = new TcpListener(localEndPoint);
tcplistener.Start(10);
}

private void button1_Click(object sender, EventArgs e)
{
Action l = () =>
{
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();

tcplistener.BeginAcceptSocket(
new AsyncCallback(AcceptCallback1),
tcplistener);

// Wait until a connection is made before continuing.
allDone.WaitOne();
}
};
l.BeginInvoke(null, null);
listView1.Items.Add("服务已开启");
button1.Enabled = false;
}

public void AcceptCallback1(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();

TcpListener listener = (TcpListener)ar.AsyncState;
Socket handler = listener.EndAcceptSocket(ar);

byte[] receive = new byte[128];
try
{
int count = handler.Receive(receive);
string request = Encoding.UTF8.GetString(receive, 0, count);
string file = Path.Combine(basePath, request);
if (File.Exists(file))
{
handler.SendFile(file);
MessageBoxShow("发送完毕");
}
}
catch (Exception ex)
{
MessageBoxShow(ex.Message);
}

}

void MessageBoxShow(string msg)
{
if (this.InvokeRequired)
{
Action showmsg = () => MessageBox.Show(msg);
this.Invoke(showmsg);
}
else
{
MessageBox.Show(msg);
}
}
}
heidong2002 2009-09-15
  • 打赏
  • 举报
回复
改了下程序,却无法运行了,晕死:
private Thread qSerTh;

private void button1_Click(object sender, EventArgs e)
{
try
{
qSerTh = new Thread(new ThreadStart(ServerIng));
qSerTh.IsBackground = true;
qSerTh.Start();
}
catch
{
MessageBox.Show("线程启动错误");
}
}
private void QQServerIng()
{
Socket s;
try
{
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Bind(qSerIpendPoint);
s.Listen(1000);
while (ServerRun)
{
s.BeginAccept(new AsyncCallback(ServerLis), s);
}
}
catch { }
}

private void ServerLis(IAsyncResult ar)
{
Socket ss = (Socket)ar.AsyncState;
Socket QS = ss.EndAccept(ar);
string msg = "";
string RemoteEndPoint = QS.RemoteEndPoint.ToString();
IPAddress remoteip = ((IPEndPoint)QS.RemoteEndPoint).Address;
int remoteport = ((IPEndPoint)QS.RemoteEndPoint).Port;
Byte[] Stream = new Byte[bufferSize];
QS.Receive(Stream);
string save = System.Text.Encoding.UTF8.GetString(Stream);
string[] ss = save.Split('|');
switch (ss[0])
{
case "Login":
break;
default://发送错误参数
break;
}
QS.Close();
}

ZSW53362465 2009-09-15
  • 打赏
  • 举报
回复
建议
建3个类
一个TransferCtrl
一个ClientTransferCtrl
一个ServerTransferCtrl
后边两个都是TransferCtrl的子类
每次有CLIENT连接上来之后在SERVERTRANSFERCTRL里创建一个Transfer(这里存有句柄,SEND RECIVE方法)一个TRANSFER对应一个客户端进行通信,这样不用担心用户登陆和文件传输的时候会乱了
BATTLERxANGE 2009-09-14
  • 打赏
  • 举报
回复
这种时候线程池不一定能提高性能
要看你的情况,你只是说有大量的用户接入,却并没有说是否高并发
如果你的大量客户要不停的接入,断开,如此反复那就用线程池。如果只是连接,而连接很长时间进行数据通讯那还是用线程吧~
BeginXXX是异步,用的还不熟,所以只用很愚蠢的方法:当有用户接入才再创建一条新的线程。如此反复
  • 打赏
  • 举报
回复
[Quote=引用楼主 heidong2002 的回复:]
     另外,有人说BeginXXX方法和EndXXX方法会利用c#内置的线程池,且性能较高,是这样吗?这种方法又如何写呢?
[/Quote]
是的。这些方法.net会自动使用.net或者操作系统专门优化用来干这个事情的线程池,不是我们普通地创建线程可比的。创建线程方法虽然比同步处理提高了效率,但是线程生命期管理的开销有时候大得侵占了大部分真正干事情的时间。
jy251 2009-09-14
  • 打赏
  • 举报
回复
beginXXX其实都是异步函数。。。。。
在调用的时候,都会自动创建一个线程去执行,并且这些线程在执行完毕之后,过一会,系统就自动回收了。

其实自己创建和beginXX两种使用线程的办法都各有千秋,各自有各自的好处。

但是beginXx用起来方便很多。
ZSW53362465 2009-09-14
  • 打赏
  • 举报
回复
3楼正解
qldsrx 2009-09-14
  • 打赏
  • 举报
回复
为什么不用qTcpListener.BeginAcceptSocket方法,这样每进来一个连接都会自动创建一个线程的啊。
LutzMark 2009-09-14
  • 打赏
  • 举报
回复
代码里哪有线程池?
System.Threading.ThreadPool
天乐 2009-09-14
  • 打赏
  • 举报
回复
推荐开源线程池:SmartThreadpool

到www.codeproject.com上面一搜即得

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧