C#网络编程(基本操作2)

接 C#网络编程(基本操作1)

3.服务端获取客户端连接

3.1获取单一客户端连接

上面服务端、客户端的代码已经建立起了连接,这通过使用“netstat -a”命令,从端口的状态可以看出来,但这是操作系统告诉我们的。那么我们现在需要知道的就是:服务端的程序如何知道已经与一个客户端建立起了连接?

服务器端开始侦听以后,可以在TcpListener实例上调用AcceptTcpClient()来获取与一个客户端的连接,它返回一个 TcpClient类型实例。此时它所包装的是由服务端去往客户端的Socket,而我们在客户端创建的TcpClient则是由客户端去往服务端的。这 个方法是一个同步方法(或者叫阻断方法,block method),意思就是说,当程序调用它以后,它会一直等待某个客户端连接,然后才会返回,否则就会一直等下去。这样的话,在调用它以后,除非得到一个 客户端连接,不然不会执行接下来的代码。一个很好的类比就是Console.ReadLine()方法,它读取输入在控制台中的一行字符串,如果有输入, 就继续执行下面代码;如果没有输入,就会一直等待下去。

   
   
   
   
  1. Console.WriteLine("Server is running .."); 
  2.             IPAddress ip = new IPAddress(new byte[]{127,0,0,1}); 
  3.             TcpListener listener = new TcpListener(ip, 801); 
  4.  
  5.             listener.Start();//开始侦听 
  6.             Console.WriteLine("Start Listening .."); 
  7.  
  8.             //获取连接 
  9.             TcpClient remoteClient = listener.AcceptTcpClient(); 
  10.  
  11.             //打印客户端信息 
  12.             Console.WriteLine("Client Connectioned!{0}-------->{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); 

运行这段代码,会发现服务端运行到listener.AcceptTcpClient()时便停止了,并不会执行下面的 Console.WriteLine()方法。为了让它继续执行下去,必须有一个客户端连接到它,所以我们现在运行客户端,与它进行连接。简单起见,我们 只在客户端开启一个端口与之连接:

  
  
  
  
  1. Console.WriteLine("Client Running .."); 
  2.             TcpClient client = new TcpClient(); 
  3.             try 
  4.             { 
  5.                 client.Connect("localhost", 801); 
  6.             } 
  7.             catch (Exception e) 
  8.             { 
  9.                 Console.WriteLine(e.Message); 
  10.                 return
  11.             } 
  12.             //打印连接到服务端信息 
  13.             Console.WriteLine("Server Connnected!{0}---->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); 

3.2获取多个客户端连接

现在我们再接着考虑,如果有多个客户端发动对服务器端的连接会怎么样,我们先看下客户端的关键代码:

  
  
  
  
  1. Console.WriteLine("Client Running .."); 
  2.            TcpClient client; 
  3.            for (int i = 0; i < 5; i++) 
  4.            { 
  5.                try 
  6.                { 
  7.                    client = new TcpClient(); 
  8.                    client.Connect("localhost", 801); 
  9.                } 
  10.                catch (Exception e) 
  11.                { 
  12.                    Console.WriteLine(e.Message); 
  13.                    return
  14.                } 
  15.                //打印连接到服务端信息 
  16.                Console.WriteLine("Server Connnected!{0}---->{1}", client.Client.LocalEndPoint, client.Client.RemoteEndPoint); 
  17.            } 

如果服务端代码不变,我们先运行服务端,再运行客户端,那么接下来会看到这样的输出:

就又回到了“多个客户端与服务端连接”中的处境:尽管有三个客户端连接到了服务端,但是服务端程序只接收到了一个。这是因为服务端只调用了一次listener.AcceptTcpClient(),而它只对应一个连往客户端的Socket。但是操作系统是知道连接已经建立了的,只是我们程序中没有处理到,所以我们当我们输入“netstat -a”时,仍然会看到3对连接都已经建立成功。

为了能够接收到三个客户端的连接,我们只要对服务端稍稍进行一下修改,将AcceptTcpClient方法放入一个do/while循环中就可以了:

  
  
  
  
  1. Console.WriteLine("Server is running .."); 
  2.             IPAddress ip = new IPAddress(new byte[]{127,0,0,1}); 
  3.             TcpListener listener = new TcpListener(ip, 801); 
  4.  
  5.             listener.Start();//开始侦听 
  6.             Console.WriteLine("Start Listening .."); 
  7.             while (true
  8.             { 
  9.                 //获取连接 
  10.                 TcpClient remoteClient = listener.AcceptTcpClient(); 
  11.  
  12.                 //打印客户端信息 
  13.                 Console.WriteLine("Client Connectioned!{0}-------->{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint); 
  14.             } 

这样看上去是一个死循环,但是并不会让你的机器系统资源迅速耗尽。因为前面已经说过了,AcceptTcpClient()再没有收到客户端的连接之前, 是不会继续执行的,它的大部分时间都在等待。另外,服务端几乎总是要保持在运行状态,所以这样做并无不可,还可以省去“按Q退出”那段代码。此时再运行代 码,会看到服务端可以收到3个客户端的连接了。

你可能感兴趣的:(socket,method,操作系统,网络编程,客户端)