TCP协议的SOCKET网络编程服务器端一对多连接的问题……求解 搞清楚TCP/IP的原理先,谁告诉你的一个连接就要开一个线程??? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 服务器端 一个监听SOCKET是公用的。但维护着与某个终端保持通信的连接SOCKET是每次监听到客户端的请求之后生成的啊? 看教程上是这样说的。这样岂不是500个人连接,服务器端就得有500个与客户端通信的SOCKET对象? 每个对象又专门挂起一个线程来执行接收客户机发来的消息的循环。还有什么更好的办法么? 大哥,愿闻其详 我才接触多线程和SOCKET不到一个月。很多东西即使查资料都找不到啊。比如长短连接是怎么回事? 线程池是怎么回事? 对于多连接的情况,最好使用IO completion port,.Net中提供的封装,你可以看看,一个线程对于一个连接是不可取的。 IO完成端口可以实现很高的性能,对于你说的500左右连接小菜一碟,.Net中的Socket类提供了现成的封装,就用这个实现 搜一搜:异步socket500个socket对象不代表就必须用500个线程去接收数据 .net中的SOCKET类有提供封装 那它究竟是哪个方法呢? 查MSDN不知道是哪个 public bool ConnectAsync( SocketAsyncEventArgs e) 1、服务器端一个Socket实例进行监听,不是连一个客户端创建一个Socket!2、使用ManualResetEvent控制线程,异步接收、应答 大哥,愿闻其详 我才接触多线程和SOCKET不到一个月。很多东西即使查资料都找不到啊。比如长短连接是怎么回事? 线程池是怎么回事?长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式 还有那些诸如完成端口,以及异步socket什么的,你也许看上去会觉得很复杂,但是那是你还没明白它们的机制,如果你是刚开始接触这个,我建议你先用简单的方法 大哥,愿闻其详 我才接触多线程和SOCKET不到一个月。很多东西即使查资料都找不到啊。比如长短连接是怎么回事? 线程池是怎么回事?长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式长连接也不过是占用服务端一个连接对象而已,占用什么线程? 难道你服务端侦听客户端数据使用的是N多线程while死循环Recieve吗 线程池的话倒不是必须的,如果你想了解。上网收C# 的ThreadPool类。看看这个的用法和介绍 大哥,愿闻其详 我才接触多线程和SOCKET不到一个月。很多东西即使查资料都找不到啊。比如长短连接是怎么回事? 线程池是怎么回事?长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式长连接也不过是占用服务端一个连接对象而已,占用什么线程?你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这 大哥,愿闻其详 我才接触多线程和SOCKET不到一个月。很多东西即使查资料都找不到啊。比如长短连接是怎么回事? 线程池是怎么回事?长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式长连接也不过是占用服务端一个连接对象而已,占用什么线程?你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这长连接只是保持连接而已,只要你客户端不要不停的给服务端发数据,服务端为什么要不停的用线程接收或发送数据??异步也好,或者动态开个线程也好,或者线程池也好,总之没有任何必要维持一个线程什么都不干就在那等数据 大哥,愿闻其详 我才接触多线程和SOCKET不到一个月。很多东西即使查资料都找不到啊。比如长短连接是怎么回事? 线程池是怎么回事?长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式长连接也不过是占用服务端一个连接对象而已,占用什么线程?你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这长连接只是保持连接而已,只要你客户端不要不停的给服务端发数据,服务端为什么要不停的用线程接收或发送数据??异步也好,或者动态开个线程也好,或者线程池也好,总之没有任何必要维持一个线程什么都不干就在那等数据所以我告诉他用短连接啊。你现在保持了连接状态,又不用线程,那下一次发送的数据服务端怎么接收? 大哥,愿闻其详 我才接触多线程和SOCKET不到一个月。很多东西即使查资料都找不到啊。比如长短连接是怎么回事? 线程池是怎么回事?长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式长连接也不过是占用服务端一个连接对象而已,占用什么线程?你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这长连接只是保持连接而已,只要你客户端不要不停的给服务端发数据,服务端为什么要不停的用线程接收或发送数据??异步也好,或者动态开个线程也好,或者线程池也好,总之没有任何必要维持一个线程什么都不干就在那等数据所以我告诉他用短连接啊。你现在保持了连接状态,又不用线程,那下一次发送的数据服务端怎么接收?无论长连接还是短连接,服务器端都是一个Socket对象在监听。所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持。 短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接,一般银行都使用短连接。 长连接简单点说就是一直保持连接,并非应答之后进行Close,而且维持一个心跳(超过一定时间,进行Close)。 http://www.cnblogs.com/chenxizhang/archive/2011/09/10/2172994.html看看这个吧.. 看完了什么都懂了... 按照某些死板的“范例”,你的所谓500个连接,它会一直使用501个线程来维系,其中一个是处理Accept的,另外500个是处理Receive的。这显然是不对的。因为500个处理Receive的线程把几乎所有时间在干什么?在阻塞!也就是所,线程不是用来处理业务,而是用来“等待”业务发生。你可能会说:我用500个线程在那里等待业务发生、等待10086有人说话、或者等待回拨,只能这样啊?!这是滥用线程的结果。因为有500个会话,那么服务器端一定就有500个TcpClient,但是这是静态的对象,不需要占用线程。只有受到一条消息要进行处理、或者需要发送一个消息时,才需要瞬间使用一个线程执行一下(也就是说让有限个数的CPU可以分时调度、切换一下这些操作)。当系统底层(外设)受到消息时,windows系统从I/O开始最终分配I/O线程来回调你的异步处理方法,而你的异步处理方法可能立刻启动一个工作线程来处理这一条消息(例如它需要80毫秒这么长时间才能处理完)、并立刻释放I/O线程(I/O线程最大可以有1024个以上,64位系统上则多几十倍)。在这之前并不需要占用什么500个线程。你可能看到只有3、4个线程就足以处理500个会话同时访问,因为这个操作依赖于底层回调。说“线程是为了接收数据的,因此需要阻塞、死等”,这显然是不对的。系统会回调你的处理程序,不用你频繁调用(或者死等)系统。搞懂了这个关系,就明白如何避免线程阻塞了。 32位系统下,.net的工作线程池最大1024个线程、I/O线程池中也是最大1024个线程。64位系统下,这两个数字大几十倍。就算是只能有5个线程,而且我们用系统线程池来分配线程来处理接收到的消息,那么够不够处理500个同时在线的客户端呢?肯定也够。因为线程池可接收的任务数远远大于最大线程数、它本身就是用来处理“任务队列”的机制,用不着你自己去搞什么队列,也用不着你自己去调度什么队列。所以这也从另外一个侧面说明了,你用不着因为担心队列的复杂机制而用500个线程去“死等”消息。最后要说明一下,在编写服务器程序时,不要使用 Socket,要使用 TcpListener。因为后者是基于windows 的独特的 IOCP机制的,有更好的性能。而前者只是为了跟 linux 的 Socket 机制相兼容而设计的。 处理不同消息,也不一定就在不同线程上。任何回调都完全可能跟调用代码是在同一个线程上执行。但是异步操作,本身就是与顺序操作不一样的思维方式!例如我们在网页的 javascript 程序中需要动态地给当前页面的<div id="top"></div>........<div id="footer"></div>两个<div>插入html代码(因为这两部分在许多页面都是相同的,因此适合动态插入),考虑到相应的html需要到服务器拉取,为了效率而必须使用并发(而非顺序)处理方式,于是我们的利用jQuery可以写 function LoadTopAndBottom(callback) { if (callback === void 0) { callback = null; } var dtd1 = jQuery.Deferred(); var dtd2 = jQuery.Deferred(); BottomLoad(jQuery("#footer"), ".", function () { dtd1.resolve(); }); TopLoad(jQuery("#top"), ".", function () { dtd2.resolve(); }); jQuery.when(dtd1, dtd2).done(function () { if (callback != null) callback(); }); }这个函数,基于另外两个异步加载函数(BottomLoad和TopLoad),它们分别在加载完毕时用第二个函数参数进行回调。既然底层是异步的,那么我们就不能假设谁先完成谁后完成,我们只有等待两个异步加载操作完毕之后,才能让 LoadTopAndBottom 方法的回调函数执行。你知道每一个页面中 javascript 能使用到的线程是很少的,所以一般把 javascript 说成是单线程的。但是因为使用了“异步形式”,所以我们就要有这种并发系统的设计思维,就跟顺序程序有不同的程序代码。异步程序设计,跟实际上有没有使用到子线程没有关系,主要是一种与顺序操作不一样的程序设计思维方式而已。 C#确实对socket通信做了很多优化和封装,但是你们觉得用异步和IOCP就没有线程么?那只是你们没有维护线程,不代表机器没有帮你开线程。说到底C#封装的还是socket。你们可以看看c++实现这个的时候有你们说的这么轻松么 很显然,LoadTopAndBottom 函数执行完毕时,页面的 top 和 footer 根本没有加载完成。在 LoadTopAndBottom 函数内部其实也都是“注册回调操作”。我用一个看起来很低级很原始的javascrip脚本代码来对照你说的“岂不是要挂起500个线程”的说法,这里不在乎编程语言的高低,主要在于编程人员的程序设计思维和知识。你在准备接收处理消息时也是立刻就执行完毕了。不用死等系统消息,系统会使用最适宜的线程来回调你的。 那你还可以说“反正代码就是0、1、0、1呢,干脆只要懂得争吵和纠结这两个数字的人就都会编程了!”得了。“用还是没有用”线程、TcpClient 是不是组合了Socket这不是问题的本质,本质是要清楚使用底层的具体流程的“好歹”问题。 说白了,你的目的不过是为了实现客户端和服务端通信(互相发包裹)你不需要研究C#是如何对socket进行封装的(包裹到底用飞机运输还是火车运输)也不应该关心它到底使用什么线程(到底是坐这一班飞机还是下一班飞机)只要包裹能到达对方手里就好了不是吗?? 那你还可以说“反正代码就是0、1、0、1呢,干脆只要懂得争吵和纠结这两个数字的人就都会编程了!”得了。“用还是没有用”线程、TcpClient 是不是组合了Socket这不是问题的本质,本质是要清楚使用底层的具体流程的“好歹”问题。学习和应用是两回事。难道现在有高级语言就不需要了解底层知识了。既然人家问的是Socket网络编程,很明显就是还在学习这个。你们说不要用Socket。用C#封装的类和机制。但是这是他想要的吗? 那你还可以说“反正代码就是0、1、0、1呢,干脆只要懂得争吵和纠结这两个数字的人就都会编程了!”得了。“用还是没有用”线程、TcpClient 是不是组合了Socket这不是问题的本质,本质是要清楚使用底层的具体流程的“好歹”问题。学习和应用是两回事。难道现在有高级语言就不需要了解底层知识了。既然人家问的是Socket网络编程,很明显就是还在学习这个。你们说不要用Socket。用C#封装的类和机制。但是这是他想要的吗?所以人家问:我想发个快递给别人,应该如何发?然后你完全不谈快递公司,而从飞机如何制造,如何创建一个快递公司,如何调度包裹开始讲? 才接触到多线程和网络通信教程上的代码是这样的using System.Threading;using System.Net;using System.Net.Sockets;namespace MyChatSoft{ public partial class ServerFrm : Form { public ServerFrm() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } #region 显示消息和异常消息 public void ShowErr(string msg, Exception ex) { ShowMsg("-----------------begin-------------------------"); ShowMsg(msg + "" + ex.Message); ShowMsg("-----------------end -------------------------"); } public void ShowMsg(string msg) { txtShow.AppendText(msg + "\r\n"); } #endregion private void btnStartListen_Click(object sender, EventArgs e) { StartListening(); } //负责监听端口 Socket sokWelcome = null; //负责和客户端Socket通信 Socket sokConnection = null; //负责监听 Thread threadWatchPort = null; //负责接收信息 Thread threadWatchMsg = null; #region 初始化并绑定监听 public void StartListening() { try { //创建IP地址 IPAddress address = IPAddress.Parse(txtIP.Text.Trim()); //创建IP节点(包含IP和端口) IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); //创建监听套接字(寻址协议,流方式,TCP协议) sokWelcome = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sokWelcome.Bind(endpoint); sokWelcome.Listen(10);//参数:指能同时处理的连接数 threadWatchPort = new Thread(WatchPort); //设置为后台线程(当所有前台线程停止后会自动关闭) threadWatchPort.IsBackground = true; threadWatchPort.Start(); ShowMsg("开始监听....."); } catch (Exception ex) { ShowErr("", ex); } } #endregion #region 监听客户连接请求 public void WatchPort() { while (true) { try { sokConnection = sokWelcome.Accept(); ShowMsg("监听" + sokConnection .RemoteEndPoint.ToString()+ "到连接啦....."); threadWatchMsg = new Thread(RecMsg); threadWatchMsg.IsBackground = true; threadWatchMsg.Start(); } catch (Exception ex) { ShowErr("", ex); } break; } } #endregion private void RecMsg() { while (true) { try { byte[] byteMsg = new byte[1024 * 1024 * 2]; int length = sokConnection.Receive(byteMsg, SocketFlags.None); if (length > 0) { string strMsg = Encoding.UTF8.GetString(byteMsg, 0, length); ShowMsg(strMsg); } } catch (Exception ex) { ShowErr("主机已关闭......", ex); } } } private void btnSend_Click(object sender, EventArgs e) { string strMsg = txtInput.Text.Trim(); byte[] byteMsg = Encoding.UTF8.GetBytes(strMsg); sokConnection.Send(byteMsg, byteMsg.Length, SocketFlags.None); } }}=====================================================根据我对教程这段代码的理解就是 启用一个监听SOCKET,挂起一个循环线程。然后这个线程处于阻塞状态,每次监听到请求 就产生一个用于和客户机通信的SOCKET,然后又使用一个线程,挂起一个循环用于接收客户机发来的消息。。这样似乎就是有多少连接就启用多少了线程。。我也知道多线程不能滥用,但我不知道有什么办法能解决这个问题……所以来问解决方案 才接触到多线程和网络通信教程上的代码是这样的using System.Threading;using System.Net;using System.Net.Sockets;namespace MyChatSoft{ public partial class ServerFrm : Form { public ServerFrm() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } #region 显示消息和异常消息 public void ShowErr(string msg, Exception ex) { ShowMsg("-----------------begin-------------------------"); ShowMsg(msg + "" + ex.Message); ShowMsg("-----------------end -------------------------"); } public void ShowMsg(string msg) { txtShow.AppendText(msg + "\r\n"); } #endregion private void btnStartListen_Click(object sender, EventArgs e) { StartListening(); } //负责监听端口 Socket sokWelcome = null; //负责和客户端Socket通信 Socket sokConnection = null; //负责监听 Thread threadWatchPort = null; //负责接收信息 Thread threadWatchMsg = null; #region 初始化并绑定监听 public void StartListening() { try { //创建IP地址 IPAddress address = IPAddress.Parse(txtIP.Text.Trim()); //创建IP节点(包含IP和端口) IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); //创建监听套接字(寻址协议,流方式,TCP协议) sokWelcome = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sokWelcome.Bind(endpoint); sokWelcome.Listen(10);//参数:指能同时处理的连接数 threadWatchPort = new Thread(WatchPort); //设置为后台线程(当所有前台线程停止后会自动关闭) threadWatchPort.IsBackground = true; threadWatchPort.Start(); ShowMsg("开始监听....."); } catch (Exception ex) { ShowErr("", ex); } } #endregion #region 监听客户连接请求 public void WatchPort() { while (true) { try { sokConnection = sokWelcome.Accept(); ShowMsg("监听" + sokConnection .RemoteEndPoint.ToString()+ "到连接啦....."); threadWatchMsg = new Thread(RecMsg); threadWatchMsg.IsBackground = true; threadWatchMsg.Start(); } catch (Exception ex) { ShowErr("", ex); } break; } } #endregion private void RecMsg() { while (true) { try { byte[] byteMsg = new byte[1024 * 1024 * 2]; int length = sokConnection.Receive(byteMsg, SocketFlags.None); if (length > 0) { string strMsg = Encoding.UTF8.GetString(byteMsg, 0, length); ShowMsg(strMsg); } } catch (Exception ex) { ShowErr("主机已关闭......", ex); } } } private void btnSend_Click(object sender, EventArgs e) { string strMsg = txtInput.Text.Trim(); byte[] byteMsg = Encoding.UTF8.GetBytes(strMsg); sokConnection.Send(byteMsg, byteMsg.Length, SocketFlags.None); } }}=====================================================根据我对教程这段代码的理解就是 启用一个监听SOCKET,挂起一个循环线程。然后这个线程处于阻塞状态,每次监听到请求 就产生一个用于和客户机通信的SOCKET,然后又使用一个线程,挂起一个循环用于接收客户机发来的消息。。这样似乎就是有多少连接就启用多少了线程。。我也知道多线程不能滥用,但我不知道有什么办法能解决这个问题……所以来问解决方案解决办法很多,关键看你理解的程度。比如上面他们说的完成端口或者异步SOCKET。你甚至可以直接使用TCPCLIENT类教程只是告诉这个东西是怎么用的 额。底层知道得不多,不太明白程序上具体应该怎么实施? 用threadpool类? winform中treelist有一列是checkbox怎么把数据保存到数据库? 我定义了一个变量id 然后在DetailsView 显示和这个ID相关的内容出错?? 新手求助关于new的用法 如何设置单选框 C# 如何保留指定的有效位数 C#数据导入数据到excel 问一个DataSet的问题 C#新手求助 各位大哥,请出手向救!!! 如何把菜单加入IE右键菜单里 C#中什么控件可以实现此类下拉框? listView怎么实现图片滑动效果???????
服务器端 一个监听SOCKET是公用的。
但维护着与某个终端保持通信的连接SOCKET是每次监听到客户端的请求之后生成的啊?
看教程上是这样说的。这样岂不是500个人连接,服务器端就得有500个与客户端通信的SOCKET对象?
每个对象又专门挂起一个线程来执行接收客户机发来的消息的循环。还有什么更好的办法么?
500个socket对象不代表就必须用500个线程去接收数据
.net中的SOCKET类有提供封装 那它究竟是哪个方法呢? 查MSDN不知道是哪个
SocketAsyncEventArgs e
)
2、使用ManualResetEvent控制线程,异步接收、应答
长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式
长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式
长连接也不过是占用服务端一个连接对象而已,占用什么线程?
长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式
长连接也不过是占用服务端一个连接对象而已,占用什么线程?
你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这
长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式
长连接也不过是占用服务端一个连接对象而已,占用什么线程?
你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这
长连接只是保持连接而已,只要你客户端不要不停的给服务端发数据,服务端为什么要不停的用线程接收或发送数据??
异步也好,或者动态开个线程也好,或者线程池也好,总之没有任何必要维持一个线程什么都不干就在那等数据
长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式
长连接也不过是占用服务端一个连接对象而已,占用什么线程?
你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这
长连接只是保持连接而已,只要你客户端不要不停的给服务端发数据,服务端为什么要不停的用线程接收或发送数据??
异步也好,或者动态开个线程也好,或者线程池也好,总之没有任何必要维持一个线程什么都不干就在那等数据
所以我告诉他用短连接啊。你现在保持了连接状态,又不用线程,那下一次发送的数据服务端怎么接收?
长连接就是指一直保持连接状态,哪怕不发送或者接收数据。这种状态肯定要一直占用一个线程。但是如果你发送完数据就关闭。然后下次要发送时再连接,就可以把资源释放了,这样就是短连接的方式,这样线程也只需要短时间的占用。然后配合线程池实现大量的连接。你可以参考一下http协议,http协议就是一种短连接的TCP通信方式
长连接也不过是占用服务端一个连接对象而已,占用什么线程?
你说的是连接占一个对象,那他为了处理接收数据会发送数据,难道不需要线程,不用线程怎么同时处理多个连接请求?异步?完成端口?他还没理解到这
长连接只是保持连接而已,只要你客户端不要不停的给服务端发数据,服务端为什么要不停的用线程接收或发送数据??
异步也好,或者动态开个线程也好,或者线程池也好,总之没有任何必要维持一个线程什么都不干就在那等数据
所以我告诉他用短连接啊。你现在保持了连接状态,又不用线程,那下一次发送的数据服务端怎么接收?
无论长连接还是短连接,服务器端都是一个Socket对象在监听。
所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持。
短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接,一般银行都使用短连接。
长连接简单点说就是一直保持连接,并非应答之后进行Close,而且维持一个心跳(超过一定时间,进行Close)。
看看这个吧.. 看完了什么都懂了...
........
<div id="footer"></div>两个<div>插入html代码(因为这两部分在许多页面都是相同的,因此适合动态插入),考虑到相应的html需要到服务器拉取,为了效率而必须使用并发(而非顺序)处理方式,于是我们的利用jQuery可以写 function LoadTopAndBottom(callback) {
if (callback === void 0) { callback = null; } var dtd1 = jQuery.Deferred();
var dtd2 = jQuery.Deferred();
BottomLoad(jQuery("#footer"), ".", function () {
dtd1.resolve();
});
TopLoad(jQuery("#top"), ".", function () {
dtd2.resolve();
});
jQuery.when(dtd1, dtd2).done(function () {
if (callback != null)
callback();
});
}
这个函数,基于另外两个异步加载函数(BottomLoad和TopLoad),它们分别在加载完毕时用第二个函数参数进行回调。既然底层是异步的,那么我们就不能假设谁先完成谁后完成,我们只有等待两个异步加载操作完毕之后,才能让 LoadTopAndBottom 方法的回调函数执行。你知道每一个页面中 javascript 能使用到的线程是很少的,所以一般把 javascript 说成是单线程的。但是因为使用了“异步形式”,所以我们就要有这种并发系统的设计思维,就跟顺序程序有不同的程序代码。异步程序设计,跟实际上有没有使用到子线程没有关系,主要是一种与顺序操作不一样的程序设计思维方式而已。
那你还可以说“反正代码就是0、1、0、1呢,干脆只要懂得争吵和纠结这两个数字的人就都会编程了!”得了。“用还是没有用”线程、TcpClient 是不是组合了Socket这不是问题的本质,本质是要清楚使用底层的具体流程的“好歹”问题。
你的目的不过是为了实现客户端和服务端通信(互相发包裹)
你不需要研究C#是如何对socket进行封装的(包裹到底用飞机运输还是火车运输)
也不应该关心它到底使用什么线程(到底是坐这一班飞机还是下一班飞机)
只要包裹能到达对方手里就好了不是吗??
那你还可以说“反正代码就是0、1、0、1呢,干脆只要懂得争吵和纠结这两个数字的人就都会编程了!”得了。“用还是没有用”线程、TcpClient 是不是组合了Socket这不是问题的本质,本质是要清楚使用底层的具体流程的“好歹”问题。
学习和应用是两回事。难道现在有高级语言就不需要了解底层知识了。既然人家问的是Socket网络编程,很明显就是还在学习这个。你们说不要用Socket。用C#封装的类和机制。但是这是他想要的吗?
那你还可以说“反正代码就是0、1、0、1呢,干脆只要懂得争吵和纠结这两个数字的人就都会编程了!”得了。“用还是没有用”线程、TcpClient 是不是组合了Socket这不是问题的本质,本质是要清楚使用底层的具体流程的“好歹”问题。
学习和应用是两回事。难道现在有高级语言就不需要了解底层知识了。既然人家问的是Socket网络编程,很明显就是还在学习这个。你们说不要用Socket。用C#封装的类和机制。但是这是他想要的吗?
所以人家问:我想发个快递给别人,应该如何发?
然后你完全不谈快递公司,而从飞机如何制造,如何创建一个快递公司,如何调度包裹开始讲?
才接触到多线程和网络通信教程上的代码是这样的using System.Threading;
using System.Net;
using System.Net.Sockets;namespace MyChatSoft
{
public partial class ServerFrm : Form
{
public ServerFrm()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
} #region 显示消息和异常消息
public void ShowErr(string msg, Exception ex)
{
ShowMsg("-----------------begin-------------------------");
ShowMsg(msg + "" + ex.Message);
ShowMsg("-----------------end -------------------------");
} public void ShowMsg(string msg)
{
txtShow.AppendText(msg + "\r\n");
}
#endregion private void btnStartListen_Click(object sender, EventArgs e)
{
StartListening();
} //负责监听端口
Socket sokWelcome = null;
//负责和客户端Socket通信
Socket sokConnection = null;
//负责监听
Thread threadWatchPort = null;
//负责接收信息
Thread threadWatchMsg = null; #region 初始化并绑定监听
public void StartListening()
{
try
{
//创建IP地址
IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
//创建IP节点(包含IP和端口)
IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
//创建监听套接字(寻址协议,流方式,TCP协议)
sokWelcome = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sokWelcome.Bind(endpoint);
sokWelcome.Listen(10);//参数:指能同时处理的连接数
threadWatchPort = new Thread(WatchPort);
//设置为后台线程(当所有前台线程停止后会自动关闭)
threadWatchPort.IsBackground = true;
threadWatchPort.Start();
ShowMsg("开始监听.....");
}
catch (Exception ex)
{
ShowErr("", ex);
}
}
#endregion #region 监听客户连接请求
public void WatchPort()
{
while (true)
{
try
{
sokConnection = sokWelcome.Accept();
ShowMsg("监听" + sokConnection .RemoteEndPoint.ToString()+ "到连接啦.....");
threadWatchMsg = new Thread(RecMsg);
threadWatchMsg.IsBackground = true;
threadWatchMsg.Start();
}
catch (Exception ex)
{
ShowErr("", ex);
}
break;
}
}
#endregion private void RecMsg()
{
while (true)
{
try
{
byte[] byteMsg = new byte[1024 * 1024 * 2];
int length = sokConnection.Receive(byteMsg, SocketFlags.None);
if (length > 0)
{
string strMsg = Encoding.UTF8.GetString(byteMsg, 0, length);
ShowMsg(strMsg);
}
}
catch (Exception ex)
{
ShowErr("主机已关闭......", ex);
}
}
} private void btnSend_Click(object sender, EventArgs e)
{
string strMsg = txtInput.Text.Trim();
byte[] byteMsg = Encoding.UTF8.GetBytes(strMsg);
sokConnection.Send(byteMsg, byteMsg.Length, SocketFlags.None);
}
}
}=====================================================
根据我对教程这段代码的理解就是 启用一个监听SOCKET,挂起一个循环线程。然后这个线程处于阻塞状态,每次监听到请求 就产生一个用于和客户机通信的SOCKET,然后又使用一个线程,挂起一个循环用于接收客户机发来的消息。。这样似乎就是有多少连接就启用多少了线程。。我也知道多线程不能滥用,但我不知道有什么办法能解决这个问题……所以来问解决方案
才接触到多线程和网络通信教程上的代码是这样的using System.Threading;
using System.Net;
using System.Net.Sockets;namespace MyChatSoft
{
public partial class ServerFrm : Form
{
public ServerFrm()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
} #region 显示消息和异常消息
public void ShowErr(string msg, Exception ex)
{
ShowMsg("-----------------begin-------------------------");
ShowMsg(msg + "" + ex.Message);
ShowMsg("-----------------end -------------------------");
} public void ShowMsg(string msg)
{
txtShow.AppendText(msg + "\r\n");
}
#endregion private void btnStartListen_Click(object sender, EventArgs e)
{
StartListening();
} //负责监听端口
Socket sokWelcome = null;
//负责和客户端Socket通信
Socket sokConnection = null;
//负责监听
Thread threadWatchPort = null;
//负责接收信息
Thread threadWatchMsg = null; #region 初始化并绑定监听
public void StartListening()
{
try
{
//创建IP地址
IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
//创建IP节点(包含IP和端口)
IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
//创建监听套接字(寻址协议,流方式,TCP协议)
sokWelcome = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sokWelcome.Bind(endpoint);
sokWelcome.Listen(10);//参数:指能同时处理的连接数
threadWatchPort = new Thread(WatchPort);
//设置为后台线程(当所有前台线程停止后会自动关闭)
threadWatchPort.IsBackground = true;
threadWatchPort.Start();
ShowMsg("开始监听.....");
}
catch (Exception ex)
{
ShowErr("", ex);
}
}
#endregion #region 监听客户连接请求
public void WatchPort()
{
while (true)
{
try
{
sokConnection = sokWelcome.Accept();
ShowMsg("监听" + sokConnection .RemoteEndPoint.ToString()+ "到连接啦.....");
threadWatchMsg = new Thread(RecMsg);
threadWatchMsg.IsBackground = true;
threadWatchMsg.Start();
}
catch (Exception ex)
{
ShowErr("", ex);
}
break;
}
}
#endregion private void RecMsg()
{
while (true)
{
try
{
byte[] byteMsg = new byte[1024 * 1024 * 2];
int length = sokConnection.Receive(byteMsg, SocketFlags.None);
if (length > 0)
{
string strMsg = Encoding.UTF8.GetString(byteMsg, 0, length);
ShowMsg(strMsg);
}
}
catch (Exception ex)
{
ShowErr("主机已关闭......", ex);
}
}
} private void btnSend_Click(object sender, EventArgs e)
{
string strMsg = txtInput.Text.Trim();
byte[] byteMsg = Encoding.UTF8.GetBytes(strMsg);
sokConnection.Send(byteMsg, byteMsg.Length, SocketFlags.None);
}
}
}=====================================================
根据我对教程这段代码的理解就是 启用一个监听SOCKET,挂起一个循环线程。然后这个线程处于阻塞状态,每次监听到请求 就产生一个用于和客户机通信的SOCKET,然后又使用一个线程,挂起一个循环用于接收客户机发来的消息。。这样似乎就是有多少连接就启用多少了线程。。我也知道多线程不能滥用,但我不知道有什么办法能解决这个问题……所以来问解决方案
解决办法很多,关键看你理解的程度。比如上面他们说的完成端口或者异步SOCKET。你甚至可以直接使用TCPCLIENT类
教程只是告诉这个东西是怎么用的
额。底层知道得不多,不太明白程序上具体应该怎么实施? 用threadpool类?