C# 基础(8)--网络编程

时间:2023-03-09 05:12:59
C# 基础(8)--网络编程

套接字,客户端连接服务器,作为进程通讯机制,是基于描述IP地址和端口,是一个通讯链的句柄,其实质就是两个程序通讯用的。

非常类似于电话插座。双方通话的过程,是一方向电话机发出信号和对方从电话机接受信号的过程,相当于Socket发送数据和从Socket接收数据,通话结束后,一方挂电话相当于关闭Socket,撤销连接。

有两种类型:

流式Socket(Stream)

是一种面向连接的Socket,针对于面向连接的TCP服务应用。安全但效率低。

数据报式(DATAGRAM)

是一种无连接的Socket ,  对应于无连接的UDP服务应用,不安全但效率高。

1、 服务端 Welcoming Socket开始监听端口,负责监听客户端连接信息。

2、 客户端 Client Socket连接服务端指定端口,负责接收和发送服务端消息。
3、服务端welcoming Socket 监听到客户端连接,创建Connection Socket,负责和客户通讯。

->服务器端Socket(至少需要2个)

一个负责接收客户端连接数据请求,(但不与客户端通讯)

每成功接收到一个客户端的连接,便在服务器端产生一个对应的Socket。

申请一个Socket

绑定到一个IP和端口上

开启侦听,等待接受连接

->客户端的Socket

必须制定要连接的服务端地址和端口

通过创建一个Socket对象来初始化一个到服务端的TCP连接。

申请一个Socket

接连服务器,指明IP地址和端口号

服务器连接到请求后,产生一个新的Socket,( 端口大于1024),于客户端建立连接并进行通讯,原侦听Socket继续侦听。

在.net下进行网络编程其实也相对比较简单,因为在.NET 类库中已经提供了大量封装好的类。比较底层的类是System.Net.Sockets.Scoket类,这个类提供了丰富的方法和属性,并且还提供了异步数据传输支持。

常见方法:

Public Scoket Accept ();为新连接创建新的Socket

Public void Bind(EndPoint localEP) 使Socket与本地终结点相关联。

Public void Close() 关闭Socket连接并释放所有有关联的资源。

PublicVoid Connect(EndPoint remoteEP)建立于远程主机的连接。

Public void Disconncet(bool reuseSocket) 关闭套接字连接并是否允许重用套接字。

Public void Listen(int backlog) 将Socket置于侦听状态

Public int Receive(byte[] buffer)接收来自绑定的Socket的数据

Public int ReceiveFrom(byte[] buffer,ref EndPoint remoteEP) 接收数据报并存储源终结点。

Public int Send(byte[] buffer) 将数据发送到接连的Socket

Public  void SendFile(string FileName) 将文件和可选数据异步发送到连接的Socket

Public int SendTo(byte[] buffer,EndPoint remoteEP)将数据发送到特定的终结点。

Pblic Void Shutdown (SocketShutDown how) 禁用某Socket上的发送和接收。

注意:

在网络传输时,传输的数据都是二进制形式的,表现为字节数组,所以如果要传输类似于中文这样的双字节字符就需要在传输之前用合适的编码转换成字节数组,然后接收方按照发送方的编码将接收到的字节数组转换为字符串,另外,注意接收数据的时候,是先声明一个字节数组,然后接收到的数据保存到字节数组汇总,这个方法有个返回值,表示实际接受了多少字节的数据,这是因为数组是不可变的,加入声明了一大于1024字节的数组,而仅发送1字节数据,而接收方并不直接到发送方发送的数据量,而是把整个1024当做发送的数据发送的话,最终会导致错误。

要实现一个服务器端的面向连接的Socket用于接收客户端的请求的话,有如下步骤:

1) 首先根据IP地址和端口号实例化一个Socket,注意端口要大于1024并且不适用特殊端口号,要大于1024的原因是1024以下的端口号已经被指派了,而1433、3306这样的端口号已经被用作SQL Sever和MySQl的默认端口号了,若指定这些端口号易发生冲突。

2) 接着调用Bind()方法进行绑定,然后再调用Listen()方法用于监听,Listen方法的参数用于指定监听的队列大小,也就是最多可容纳的等待接受的传入的接连数。

3) 再调用Accept()方法,调用这个方法之后会是程序处于阻塞状态,直至有客户端连接为止,当有客户端接连,这个方法将会返回一个新的Socket,使用这个Socket与客户端进行通讯。

4) 使用Accept()方法返回的新的Socket的Send()方法就可以向客户端发送数据了,还可以使用这个新Socket的Receive()接收客户顿的数据。

5) 最后,终止与客户端会话时,注意使用ShutDown()方法关闭Socket连接,并且使用Close方法,释放锁占用的资源。

使用Socket类编写客户端的Socket程序步骤如下:

1) 首先,指定远程主机和端口号实例化Socket类,注意连接的端口号一定要与服务器监听的端口号一致。

2) 接着调用Connect()方法连接远程主机。

3) 连接到远程主机之后就可以调用Send()方法向服务器发送请求了,然后可以调用Receive()方法,接收服务器响应数据,注意如果是发送的类似于中文这样的双字节字符串的话,还需要按照服务器响应的字符串编码将字节数组转换成字符串。

4) 最后终止与客户端会话时,注意使用ShutDown()关闭Socket连接,并且使用Close()方法释放所占用的资源。

需要特别说明的是上面是建立连接式Socket(如建立TCP协议Socket)的一般步骤,如果是建立非连接式Socket(如UDP协议Socket)就不需要进行监听端口了,直接使用ReceiveFrom()方法就能接收来自指定主机端口的数据,用SendTo()方法就能向直接主机端口发送数据。