C#套接字socket概述
一、摘要
通过最近一段时间应用C#进行网络通信,了解了C#实现网络通信的方法,尤其是套接字socket的使用,接下来的几篇文章对套接字的使用及常用传输协议TCP、UDP的C#实现做一下梳理与总结。该篇博文仅对socket涉及到的名词进行解释与区别。
二、实验平台
Visual Studio 2010
三、实验原理
这里以最常用的C/S模式作为范例,首先,服务端有一个进程(或多个进程)在指定的端口等待客户来连接,服务程序等待客户的连接信息,一旦连接上之后,就可以按设计的数据交换方法和格式进行数据传输。
在进行socket编程时,常遇到的名词还有同步、异步、阻塞和非阻塞等,下面对其做一下梳理。另外,需要说明的是,这些概念并不局限于socktet。
3.1 同步与异步
(1) 同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是处于等待状态,只有接收到返回的值或消息后才往下执行其他的命令。
(2) 异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。
在网上看到一个比较形象的例子,摘录如下:
设想你是一位体育老师,需要测验100位同学的400米成绩。你当然不会让100位同学一起起跑,因为当同学们返回终点时,你根本来不及掐表记录各位同学的成绩。如果你每次让一位同学起跑并等待他回到终点你记下成绩后再让下一位起跑,直到所有同学都跑完。恭喜你,你已经掌握了同步阻塞模式。
你设计了一个函数,传入参数是学生号和起跑时间,返回值是到达终点的时间。你调用该函数100次,就能完成这次测验任务。这个函数是同步的,因为只要你调用它,就能得到结果;这个函数也是阻塞的,因为你一旦调用它,就必须等待,直到它给你结果,不能去干其他事情。
如果你一边每隔10秒让一位同学起跑,直到所有同学出发完毕;另一边每有一个同学回到终点就记录成绩,直到所有同学都跑完。恭喜你,你已经掌握了异步非阻塞模式。
你设计了两个函数,其中一个函数记录起跑时间和学生号,该函数你会主动调用100次;另一个函数记录到达时间和学生号,该函数是一个事件驱动的callback函数,当有同学到达终点时,你会被动调用。你主动调用的函数是异步的,因为你调用它,它并不会告诉你结果;这个函数也是非阻塞的,因为你一旦调用它,它就马上返回,你不用等待就可以再次调用它。但仅仅将这个函数调用100次,你并没有完成你的测验任务,你还需要被动等待调用另一个函数100次。
当然,你马上就会意识到,同步阻塞模式的效率明显低于异步非阻塞模式。那么,谁还会使用同步阻塞模式呢?
不错,异步模式效率高,但更麻烦,你一边要记录起跑同学的数据,一边要记录到达同学的数据,而且同学们回到终点的次序与起跑的次序并不相同,所以你还要不停地在你的成绩册上查找学生号。忙乱之中你往往会张冠李戴。
你可能会想出更聪明的办法:你带了很多块秒表,让同学们分组互相测验。恭喜你!你已经掌握了多线程同步模式!
每个拿秒表的同学都可以独立调用你的同步函数,这样既不容易出错,效率也大大提高,只要秒表足够多,同步的效率也能达到甚至超过异步。
可以理解,你现的问题可能是:既然多线程同步既快又好,异步模式还有存在的必要吗?
很遗憾,异步模式依然非常重要,因为在很多情况下,你拿不出很多秒表。你需要通信的对端系统可能只允许你建立一个socket连接,很多金融、电信行业的大型业务系统都如此要求。
以上即是socket编程中同步与异步的区别。
3.2 阻塞与非阻塞
(1)阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。
(2)非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
3.3 同步与阻塞的区别
针对上述的阐述,有人也许会把阻塞和同步等同起来,实际上他是不同的。同步异步与阻塞和非阻塞是两种不同的概念来着,同步异步指的是通信模式,而阻塞和非阻塞指的是在接收和发送时是否等待动作完成才返回,所以不能混淆这四个词。