文章目录
前言一、Socket 对象二、Bind() 绑定与 Connect() 连接三、Listen() 监听请求连接 和 Accept() 接收连接请求四、Receive() 与 Send()五、释放资源六、IPAddress 和IPEndPoint
前言
文章按照 Socket 的 创建、连接、传输数据、释放资源的过程来写。给出方法、参数的详细信息。
一、Socket 对象
无论是服务器还是客户端,都要创建一个 SOCKET 对象,创建方法一致。
以下是常见的Socket对象创建实例
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//监控 ip4 地址,套接字类型为 TCP ,协议类型为 TCP
其有三个构造函数
public Socket(SocketInformation socketInformation);public Socket(SocketType socketType, ProtocolType protocolType);public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType);
第一个构造函数,SocketInformation 对象保存的是
Socket(SocketType, ProtocolType)
实质上跟第二个构造函数是一样的。就好像你可以直接把( 一个苹果 , 一个梨)直接放进篮子,也可以先给 水果包装好 再放进篮子里。
下面将解释所有参数的意义。
SocketType
指定 Socket 类的实例表示的套接字类型。
TCP 用主机的IP地址加上主机上的端口号作为 TCP 连接的端点,这种端点就叫做套接字(socket)或插口。 套接字用(IP地址:端口号)表示。
SocketType 是enum 类型,其字段如下
ProtocolType
表示协议类型,是一个enum 类型。
其所有字段如下
AddressFamily
表示使用的网络寻址方案,是一个 enum 类型。
二、Bind() 绑定与 Connect() 连接
Bind() 用于绑定IPEndPoint 对象,在服务端使用。
Connect() 在客户端使用,用于连接服务端。
创建 Socket 对象后,接着绑定本地Socket / 连接服务端。
Bind()
public void Bind (System.Net.EndPoint localEP);
使用方法
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress iP = IPAddress.Parse("127.0.0.1"); //上面不重要,看下面//IPEndPoint iPEndPoint = new IPEndPoint(iP, 2300);//serverSocket.Bind(iPEndPoint); serverSocket.Bind(new IPEndPoint(iP, 2300))
你将在在本地创建IPEndPoint 对象,拥有此 ip:post 的访问权限。目的是绑定本地机器的某个端口,所有经过此端口的数据就归你管了。
Connect()
与远程主机建立连接。Connect() 有四个重载方法,不必关注,只需知道,必需提供 IP 和 Post 两个值。
使用方法
IPAddress iP = IPAddress.Parse("127.0.0.1"); IPEndPoint iPEndPoint = new IPEndPoint(iP, 2300); Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建与远程主机的连接 serverSocket.Connect(iPEndPoint);
三、Listen() 监听请求连接 和 Accept() 接收连接请求
Listen()
监控所有发送到此主机的、特点端口的连接请求。服务端使用,客户端不需要。
public void Listen (int backlog);
使用 Bind() 后,使用 Listen() 方法进行监控,backlog 参数指定可排队等待接受的传入连接的数量,即挂起的连接队列的最大长度。
示例
serverSocket.Listen(10); //开始监听
Accept()
Accept() 以同步方式监听套接字,在连接请求队列中提取第一个挂起的连接请求,然后创建并返回一个新的 Socket 对象。
代码示例
//创建终结点(EndPoint)IPAddress ip = IPAddress.Any; IPEndPoint ipe = new IPEndPoint(ip, 8000); //创建 socket 并开始监听Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);serverSocket.Bind(ipe);serverSocket.Listen(10);//开始监听 //接受到client连接,为此连接建立新的socket,并接受信息Socket temp = serverSocket.Accept();//为新建连接创建新的socket
//关闭连接temp.Close();
注意的是,每次建立连接是一个 Accept() 对象,如果你要进行 服务器-客户端互相通讯,应使用同一个 Accept() 对象。每个 Accept 对象都是 从客户端请求建立开始的,期间只要使用同一个 Accept 对象,都可以进行数据传输。
四、Receive() 与 Send()
Receive() 接收信息
Send() 发送信息
在服务端和客户端都使用这两个方法。
Receive()
使用示例
string recvStr = "";byte[] recvBytes = new byte[1024];int bytes;bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
直接从微软那复制来的。
参数
Byte[] buffer
Byte类型的数组,它是存储接收到的数据的位置。
Int32 offset
buffer参数中的位置,用于存储所接收的数据。
Int32 size
要接收的字节数。
SocketFlags socketFlags
SocketFlags值的按位组合。
SocketError errorCode
一个SocketError对象,它存储套接字错误。
socketFlags 默认值为0 或 None ,笔者没有搞懂socketFlags 的应用场景。
返回
返回已成功读取的字节数。
Send()
send()跟Receive()用法相似,
示例代码如下
string str = "hello";byte[] a = Encoding.UTF8.GetBytes(str);send = socket.Send(a, 0);
发送/接收 都是使用 byte[] 字节流,所以接收时要进行转换。
五、释放资源
有 Accept 释放和 Socket 的释放。
Accept 是连接对象,一个 Socket 可能有数十个 Accept 连接。
使用 Shutdown( ) 方法可以 禁止 Asscpt 对象的操作(禁用某个 Socket 对象 的发送和接收)。
public void Shutdown (System.Net.Sockets.SocketShutdown how);
SocketShutdown 是一个 enum 类型。
实例
temp.Shutdown(SocketShutdown.Receive);//禁止接收
close()
会直接释放资源,Accept 和 Socket 对象都可以使用。使用后对象将彻底释放。
六、IPAddress 和IPEndPoint
//引入using System.Net;
IPAddress 用来处理IP地址、转换IP地址
IPAddress.Parse() 方法可以把以小数点隔分的十进制 IP 表示转化成 IPAddress 类。
IPAddress ip = IPAddress.Parse("127.0.0.1");//把ip地址字符串转换为IPAddress类型的实例
IPAddress提供4个只读字段
Any 用于代表本地系统可用的任何IP地址
Broadcase用于代表本地网络的IP广播地址
Loopback用于代表系统的回送地址
None用于代表系统上没有网络接口
IPEndPoint 表示IPAddress对象与端口的绑定
IPAddress ip = IPAddress.Any; //把ip地址字符串转换为IPAddress类型的实例IPEndPoint ipe = new IPEndPoint(ip, 8000);//用指定的端口和ip初始化IPEndPoint类的新实例
上面的代码,创建一个监控点,端口是 8000,对象是 本地所有IP。
另外,此类能够获取查看端口的值范围,除此外,此类没有太大意义。