服务端获取客户端连接


1. 获取单一客户端连接

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

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

class Server {
	static void Main(string[] args) {
		Console.WriteLine("Server is running ... ");
		IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 }); 
		TcpListener listener = new TcpListener(ip, 8500); listener.Start();           // 开始侦听
		Console.WriteLine("Start Listening ...");
		// 获取一个连接,中断方法
		TcpClient remoteClient = listener.AcceptTcpClient();
		// 打印连接到的客户端信息
		Console.WriteLine("Client Connected!{0} <-- {1}",
			remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);
		// 按 Q 退出
	}
}

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

class Client {
	static void Main(string[] args) {
		Console.WriteLine("Client Running ...");
		TcpClient client = new TcpClient();
		try {
			client.Connect("localhost", 8500);      // 与服务器连接 
		} 
		catch (Exception ex) { 
			Console.WriteLine(ex.Message);
			return;
		}
		// 打印连接到的服务端信息
		Console.WriteLine("Server Connected!{0} --> {1}",
		client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
		// 按 Q 退出
	}
}

此时,服务端、客户端的输出分别为:

// 服务端
Server is running ...
Start Listening ...
Client Connected!127.0.0.1:8500 <-- 127.0.0.1:5188
// 客户端
Client Running ...
Server Connected!127.0.0.1:5188 --> 127.0.0.1:8500

2. 获取多个客户端连接

现在我们再接着考虑,如果有多个客户端发动对服务器端的连接会怎么样,为了避免你将浏览器向上滚动,来查看上面的代码,我将它拷贝了下来,我们先看下客户端的关键代码:

TcpClient client;

for (int i = 0; i <=2; i++) {
	try {
		client = new TcpClient(); 
		client.Connect("localhost", 8500);      // 与服务器连接 
	} 
	catch (Exception ex) { 
		Console.WriteLine(ex.Message);
		return;
	}
	// 打印连接到的服务端信息
	Console.WriteLine("Server Connected!{0} --> {1}",
	client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
}

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

// 服务端
Server is running ...
Start Listening ...
Client Connected!127.0.0.1:8500 <-- 127.0.0.1:5226
// 客户端
Client Running ...
Server Connected!127.0.0.1:5226 --> 127.0.0.1:8500 Server Connected!127.0.0.1:5227 --> 127.0.0.1:8500 Server Connected!127.0.0.1:5228 --> 127.0.0.1:8500

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

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

Console.WriteLine("Start Listening ...");

while (true) {
	// 获取一个连接,同步方法
	TcpClient remoteClient = listener.AcceptTcpClient();
	// 打印连接到的客户端信息
	Console.WriteLine("Client Connected!{0} <-- {1}",
		remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);
}

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

Server is running ...
Start Listening ...
Client Connected!127.0.0.1:8500 <-- 127.0.0.1:5305 
Client Connected!127.0.0.1:8500 <-- 127.0.0.1:5306 
Client Connected!127.0.0.1:8500 <-- 127.0.0.1:5307

本篇文章到此就结束了,接下来一篇我们来看看如何在服务端与客户端之间收发数据。

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
YES开发框架
下一篇:Part2
评论列表

发表评论

评论内容
昵称:
关联文章

服务获取客户连接
2.客户服务连接
客户发送,服务接收并输出
服务回发,客户接收并输出
客户接收文件
客户发送数据
客户的实现
服务实现
GZUpdate自动升级服务 .NET C/S Winform客户程序自动升级演示
FTP客户工具 WinSCP ( 推荐,免费 )
GZUpdate自动升级程序客户演示
FTP客户工具 FileZilla
FTP服务软件 Xlight
FTP客户工具 FlashFXP (推荐)
网易闪电邮客户中配置企业邮箱的方法
1.服务对端口进行侦听
ABP VNext框架中Winform终端的开发和客户授权信息的处理
FTP服务软件 Serv-U
Python windows服务报错: 1063 StartServiceCtrlDispatcher 服务进程无法连接服务控制器上
Winform中使用HttpClient与后api服务进行交互