.NET Socket开发之同步Socket实现两例

转载 2007年10月15日 15:20:00

.NET Socket开发之同步Socket实现两例  

NET Socket开发之同步Socket实现两例

今天,我们来讲一下在.NET 网络应用程序开发中同步Socket的应用,很多人认为在网络应用的服务端Socket不应该使用同步Socket。是的,在大多数情况下是这样的,但是也有一些场景下我们使用同步Socket可能会得到更的结果。如在下面的两种场景下我们便可以考虑使用同步的Socket。
一、客户端数量比较少:
数量比较少是指会同时连接到服务器的客户端数量一般在50人以下。这种情况下我们可以考虑使用同步Socket+Thread来实现我们的服务端。这样会让我们编写逻辑更清晰的代码而性能不会下降太多。
二、客户端数量较多但都是短连接:
短连接是指客户端的连接在处理完一次收发之后就产即断开的场景,比如说HTTP协议就是一种短连接。HTTP在客户端发出请求时建立一个Socket连接,并通过Socket发出一个URL请求,服务端在处理完这个请求并回发相应的页面后便会断开这个连接。那么在这种场景下我们也可以使用同步Socket来实现我们的需求。
那么应该如果实现我上面提到的两种需求呢。对于这两种需求,我将采用不同的方案来实现它们。
首先我们来看看第一种需求,这里我采用Socket+Thread来实现,基本的流程如下:
首先创建一个Socket,并且给它绑定一个EndPoint后开始监听。接下来我们创建一个线程,在这个线程中我们用一个无限循环来接收来自客户端的连接请求。在接收到一个请求后,为这个客户端创建一个新的线程,并且在这个线程中也使用一个无限循环接收来自这个客户端的数据。下面让我们来看看代码:
 
首先我们创建一个Socket用来侦听客户端的连接:
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint locEP
= new IPEndPoint(IPAddress.Any, 2000);
listener.Bind(locEP);
listener.Listen(
100);
然后创建一个线程来处理客户端的连接请求:
Thread acceptThread = new Thread(new ThreadStart(AcceptWorkThread));
acceptThread.Start();
 
private void AcceptWorkThread()
{
    Thread.CurrentThread.IsBackground 
= true;
    
while (true)
    
{
        Socket accept 
= listener.Accept();
        IPEndPoint remoEP 
= (IPEndPoint)accept.RemoteEndPoint;
        
string recString = "接收到来自" + remoEP.Address.ToString() + "的连接。";
        
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
        Thread receiveThread 
= new Thread(new ParameterizedThreadStart(ReceiveWorkThread));
        receiveThread.Start(accept);
    }

}
最后我们来看看如何接收数据:
private void ReceiveWorkThread(object obj)
{
    Thread.CurrentThread.IsBackground 
= true;
    Socket socket 
= (Socket)obj;
    
byte[] buffer = new byte[1024];
    
while (true)
    
{
        
int receiveCount = socket.Receive(buffer);
        
if (receiveCount > 0)
        
{
            IPEndPoint remoEP 
= (IPEndPoint)socket.RemoteEndPoint;
            
string recString = "来自客户端" + remoEP.Address.ToString() + "的消息:" + Encoding.Default.GetString(buffer, 0, receiveCount);
            
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
            socket.Send(buffer, receiveCount, SocketFlags.None);
        }

        
else
        
{
            socket.Close();
            
break;
        }

    }

}
好了,整个实现就完成了。
现在让我们来看看第二个需求:
这个方案我们将采用另外一个方法来实现,为什么不采用上一个方法来实现呢?让我们来分析一下。我们知道,在上一个实现中,每接入一个客户端就要创建一个线程,如果有大量的客户端接入的话,就会创建过多的线程。但是如果线程过多的话,Windows就需要更多的CPU时间来切换线程的上下文(这也是上一个实现不能接入很多客户端的原因)。
我们知道,在这个方案中每一个连接都是短连接。而且顺序都是固定的。都是:接入->接收->发送这样的顺序,那么我们就可以在一个方法中完成整个处理。这样,我们就可以利用线程池来实现我们所需要的。好了,让我们用代码来说话吧:
 
首先我们创建一个Socket用来侦听客户端的连接:
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint locEP
= new IPEndPoint(IPAddress.Any, 2000);
listener.Bind(locEP);
listener.Listen(
100);
接下来我们要创建一个线程池:
Thread[] ClientThreadList = new Thread[30];
foreach (Thread th in ClientThreadList)
{
    th 
= new Thread(new ThreadStart(ClientWorkThread));
    th.Start();
}
最后让我们看看线程都要做些什么:
private void ClientWorkThread()
{
    
byte[] buffer = new byte[1024];
    
while (true)
    
{
        Socket socket 
= listener.Accept();
        
string recString = "接收到来自" + remoEP.Address.ToString() + "的连接。";
        
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
        
int receCount = socket.Receive(buffer);
        
if (receCount>0)
        
{
            
string recString = "来自客户端" + remoEP.Address.ToString() + "的消息:" + Encoding.Default.GetString(buffer, 0, receiveCount);
            
this.Invoke(new AddListItemHandler(this.AddListItem), new string[] { recString });
            socket.Send(buffer, receCount, SocketFlags.None);
        }

        socket.Shutdown(SocketShutdown.Both);
        socket.Close();
    }

}
为什么我们要这样做呢?
首先我们创建了一个Socket用于侦听客户端的连接请求,接下我们创建了一个拥有30个线程的线程池。并在每个线程中实现了Accept、Receive、Send和Close(),以完成连接、接收、发送、关闭的操作。
现在我们假设有一个客户连接到服务器了,这时会有一个线程Accept到这个请求,并开始接收客户端发送过来的数据,接收到数据之后处理完发送给客户端,然后关闭这个连接,再次进入等待连接状态。而其它29个线程由于没有Accept到这个请求,仍然处理等待接入状态。
相信现在大家都看明白了吧,如果还有不明白的地方,欢迎大家来联系我:

.NET Socket开发之同步Socket实现两例

今天,我们来讲一下在。NET 网络应用程序开发中同步Socket的应用,很多人认为在网络应用的服务端Socket不应该使用同步Socket.是的,在大多数情况下是这样的,但是也有一些场景下我们使用同步...
  • jianxiake318
  • jianxiake318
  • 2013年11月01日 15:12
  • 255

.NET Socket开发之同步Socket实现两例

在基于.NET的网络服务端的开发中,我们用到和听到的最多的恐怕就是异步Socket了。异步Socket的性能比同步高出很多,但是编写代码比较复杂。因此异步Socket也是网络上讨论比较多的话题。 今...
  • qq_27930429
  • qq_27930429
  • 2016年12月15日 20:06
  • 98

Socket 同步和异步模式

学习socket 的一些笔记,希望和大家一起讨论 。 一.什么是socket   所谓socket通常也称作"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。 以J2SDK-1.3...
  • huijunma2010
  • huijunma2010
  • 2016年04月21日 15:04
  • 247

C#中Socket通信编程的同步实现

 本文通过分析和总结C#中Socket通信编程的关键技术,按照同步实现的方式实现了一个简单的Socket聊天程序,目的是通过这个程序来掌握Socket编程,为进一步开发Unity3D网络游戏打下...
  • mss359681091
  • mss359681091
  • 2016年06月30日 15:44
  • 5116

.NET Socket开发之同步Socket实现

转载自 http://dotnet.chinaitlab.com/ASPNET/731870.html         很多人认为在网络应用的服务端Socket不应该使用同步Socket.是的,在大...
  • biychen
  • biychen
  • 2014年02月18日 16:26
  • 518

C#中的socket编程入门实例

Socket主要是通过TCP或者UDP协议进行多台主机之间的通讯。由于项目中用到,所以今天就结合项目需求对socket编程的C#表示进行一步一步详细的介绍。 TCP的详细过程我就不多介绍了,这个是网...
  • mevicky
  • mevicky
  • 2015年10月09日 15:57
  • 13724

Java Socket 通信(同步阻塞式I/O)

java实现socket通信比较简单,因为它提供了ServerSocket 和Socket类。如下为一个简单的实例:TimeServer与TimeClient1 TimeServerpublic cl...
  • ouyang111222
  • ouyang111222
  • 2016年04月06日 18:23
  • 2802

一个简单地socket通讯Demo

首先贴出来我的项目结构。非常简单,new一个java project,在src下建一个名为socketDemo的package。在包里有两个java文件,一个是客户端,一个是服务端。 第二步,...
  • a714832876
  • a714832876
  • 2015年05月19日 12:10
  • 1291

异步SOCKET与同步SOCKET

Windows套接字在两种模式下执行I/O操作,阻塞和非阻塞。在阻塞模式下,在I/O操作完成前,执行操作的Winsock函数会一直等待下去,不会立即返回程序(将控制权交还给程序)。而在非阻塞模式下,W...
  • baidu_19340981
  • baidu_19340981
  • 2014年09月16日 14:42
  • 2000

C#中Socket通信编程的同步实现

本文通过分析和总结C#中Socket通信编程的关键技术,按照同步实现的方式实现了一个简单的Socket聊天程序,目的是通过这个程序来掌握Socket编程,为进一步开发Unity3D网络游戏打下一个坚实...
  • qinyuanpei
  • qinyuanpei
  • 2015年03月23日 21:32
  • 3771
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:.NET Socket开发之同步Socket实现两例
举报原因:
原因补充:

(最多只允许输入30个字)