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#内置的线程池,且性能较高,是这样吗?这种方法又如何写呢?
...全文
764 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用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上面一搜即得
写在前面的话: 基于HPSocket开发的C/S快速开发框架,引用怪兽群的话“不要怀疑HPSocket,有问题多看DEMO!”,这是对HPSocket稳定高效的最佳诠释!所以,基于HPSocket设计了一些周边功能,方便大家快速开发软件!那么,模块究竟有什么功能呢? 1、数据库连接池: 目前仅支持MYSql数据库,支持设定初始和最大连接数、支持请求超时、支持心跳、支持最大和最小空闲数、支持最大空闲时间检测等等各项功能。至于连接池是用来干什么的,简单的说就是用空间换时间,提前搞N个连接,当有sql请求的时候,从这N个连接中选取空闲连接进行数据库操作。 2、线程池: 这个线程池最大的亮点就是支持线程优先级。啥意思?比如数据库进行增删改操作,又有cha询操作,那么增删改的优先级肯定是要高于cha询优先级的。 3、上传池和下载池: 支持多线程、4G+文件、多客户Duan同时收发,自动分包组包。 4、缓存池: 相信很多人都喜欢用内存搞缓存池,但是搞的多了,回收再不及时的话,容易造成内存泄露。所以,这个缓存池采用临时文件读写方式进行操作,效率虽说逊色内存操作,但是其他方面的优越性是内存缓存池无法比拟的!比如在硬盘空间允许的情况下,缓存池可以无限大,缓存池可以长时间存在,而不用担心内存爆掉的问题。 5、CExcel: 封装了EXCEL相关COM调用方式,命令简洁易懂; 6、CJson: 封装了JS3,支持快速生成和解析JSON文本; 7、参数表: 用于SQL参数化处理!这有啥用?SQL注入攻击相信大家都听过,使用这个方法可以杜绝SQL注入攻击; 8、请求池: 顾名思义,用于处理请求的!这个有啥好说道说道的?规范了请求格式,参数有通信密钥、 协yi头、请求参数、附加数据,支持生成同时含有文本和字节集的请求!另外,请求内部处理了签名问题!啥意思?类似于sign签名,保证请求一致性和完整性。 9、日志池: 支持多线程、多日志同时读写; 10、事件池: 支持多事件同时处理; 11、提示框: 当鼠标悬停在控件上,会跳出提示。封装了tooltips,命令稍微优化了下,更简洁明了。 ············· ⊙﹏⊙b汗,实在吹不下去了,容易被各位大佬XXX·············

111,095

社区成员

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

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

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