C#网络编程(1)
1、Purpose
1、什么是网络编程
2、TCP/IP协议
3、什么是套接字
4、多线程深入理解
二、Basic Concept
1、网络编程:主要实现进程(线程)相互之间的通信和基本的网络应用原理性(协议)功能的程序。
2、TCP/IP是一个协议族,其中包括TCP、IP、UDP、ICMP、RIP、TELNET、FTP、SMTP、ARP、TFTP等许多协议.
TCP(Transmission Control Protocol)传输控制协议
IP(Internet Protocol)网际协议
UDP(User Datagram Protocol)用户数据报协议
ICMP(Internet Control Message Protocol)互联网控制信息协议
SMTP(Simple Mail Transfer Protocol)简单邮件传输协议
SNMP(Simple Network manage Protocol)简单网络管理协议
FTP(File Transfer Protocol)文件传输协议
ARP(Address Resolation Protocol)地址解析协议
TCP/IP从某种角度上来说由四个层次构成:网络接口层、网络层、传输层、应用层.
各层所遵守的协议
具体看看TCP协议
TCP是Transmission Control Protocol(传输控制协议)的简称,是TCP/IP体系中面向连接的运输层协议,在网络中提供全双工的和可靠的服务。
TCP协议最主要的特点是:
1) 是一种基于连接的协议。
2) 全双工、点对点。
3) 保证各数据到达的顺序与数据发出的顺序相同。
4) 传输的数据无消息边界。
解释:(1)是一种基于连接的协议:意思是说连个远程主机(或曰进程)必须进行一次握手过程,确认连接成功之后才能传输实际数据。举个例子A向B发送数据,首先要建立连接,如何建立连接呢,它首先得知道B的位置吧,也就是主机地址,然后要知道从哪个门进去吧,也就是端口号,当知道这些之后它还需要知道B要不要接收它发过来的数据吧,也就是是否满足某种协议,于是A发送一个不含任何数据的请求报文给B来试探B 让不让发送数据,如果B在接收到这个请求之后做出了回应,那么A随后才发送实际数据。
(2)全双工、点对点:如果两个主机上的进程建立好连接,那么数据就可以从A发送到B,也可以从B发送到A,点对点指的是一个TCP连接是两者之间的,不允许第三者插足,通过一个连接将数据发给多个接收方是不可能的。
(3)保证各数据到达的顺序:建立连接后,数据的发送一定能够到达,并且是有序的,发送的时候是ABC,接收的时候一定是ABC
(4)传输的数据无消息边界:说的是不能保证来自单个Send方法的数据能被单个Receive方法读取。举个例子:
第一次发送:abcdefg 第二次发送:123456 接收方接收数据时,可能会出现以下情况:
第一次接收:abcdefg123456 也可能出现:第一次接收:abc 第二次接收:efg12 第三次接收:3456
因此要解决TCP发送消息与接收消息一致性,编程时必须要解决消息边界问题。
三种方式解决传输无消息边界问题:
第一种方法是发送固定长度的消息。该方法适用于消息长度固定的场合。
第二种方法是将消息长度与消息一起发送。
第三种方法是使用特殊标记分隔消息。
3、套接字SOCKET
Windows Sockets以UNIX中流行的Socket接口为范例定义了一套Microsoft Windows网络编程接口。Windows Sockets规范旨在提供给应用程序开发人员一套简单的API,并让各家网络软件供应商共同遵守。Windows Sockets 1.1和Berkeley Sockets都是基于TCP/IP协议的;Windows Sockets 2从Windows Sockets 1.1发展而来,与协议无关并向下兼容,可以使用任何底层传输协议提供的通信能力,来为上层应用程序完成网络数据通信,而不用关心底层网络链路通信的情况,真正实现了底层网络通信对应用程序的透明。
套接字有两种不同的类型:流套接字和数据报套接字。
TCP/IP的Socket则提供3种类型的套接字
(1)流式套接字(SOCK_STREAM)
提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传输 协议(FTP)即使用流式套接字。
(2)数据报式套接字(SOCK_DGRAM)
提供无连接服务。数据包以独立包形式发送,不提供无差错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。
(3)原始套接字(SOCK_RAW)
该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。
套接字编程原理
服务器端程序执行步骤如下。
(1)打开一个通信通道并告知本地主机,它愿意在某一地址和端口上接收客户请求。
(2)等待客户请求到达该端口。
(3)接收到重复服务请求,处理该请求并发送应答信号。接收到并发服务请求,激活一个新的进程(或线程)来处理这个客户请求。新进程(或线程)处理此客
户请求, 并不需要对其他请求作出应答。服务完成后,关闭此新进程与客户的通信链路,并终止。
(4)返回第二步,等待另一客户请求。
(5)关闭服务器。
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认
(1)服务器监听
服务器监听时服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
(2)客户端请求
客户端请求是指由客户端的套接字发出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端
套 接字的地址和端口号,然后再向服务器端套接字提出连接请求。
(3)连接确认
连接确认是指当服务器端套接字监听到(或接收到)客户端套接字的连接请求时,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客
户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
以上复制了一大堆,说白了套接字Socket提供的是应用程序和传输层的接口,在这个口外口内我们不需要知道它们干了什么,那是其他层的工作。
.NET程序集提供了两个类对套接字进行了封装:TcpClient 和 TcpListener
从上面图中可以看出TcpClient和TcpListener对套接字进行了封装。从中也可以看出,TcpListener用于接受连接请求,而TcpClient则用于接收和发送流数据。这幅图的意思是TcpListener持续地保持对端口的侦听,一旦收到一个连接请求后,就可以获得一个TcpClient对象,而对于数据的发送和接收都有TcpClient去完成。此时,TcpListener并没有停止工作,它始终持续地保持对端口的侦听状态。
我们考虑这样一种情况:两台主机,主机A和主机B,起初它们谁也不知道谁在哪儿,当它们想要进行对话时,总是需要有一方发起连接,而另一方则需要对本机的某一端口进行侦听。而在侦听方收到连接请求、并建立起连接以后,它们之间进行收发数据时,发起连接的一方并不需要再进行侦听。因为连接是全双工的,它可以使用现有的连接进行收发数据。而我们前面已经做了定义:将发起连接的一方称为客户端,另一段称为服务端,则现在可以得出:总是服务端在使用TcpListener类,因为它需要建立起一个初始的连接。
在上面的链接中有对聊天的三种模式详细介绍