在C#中,实现了很多对Windows API的封装,在套接字通信方面也是如此。下面是一个TCP网络通信的简单实例,因为自己初学C#,记下来学习
使用名字空间:
using System.Net;using System.Net.Sockets;
服务器端
五个步骤:
- (1) 创建一个TcpListener类的对象,也叫“侦听器”,通过它,服务器能监听到客户的请求。
- 下面是TcpListener构造函数的3种实现: | TcpListener(Int32) | 在指定端口号进行监听,现在比较少用 | | :—-: | —- | | TcpListener(IPEndPoint) | 绑定端点(包括IP和端口号) | | TcpListener(IPAddress, Int32) | 绑定IP和端口号,TcpListener类封装了套接字的创建(socket)和绑定(bind),简化了编程的输入 | | IPAddress类有一个方法Parse() | 可以将IP 地址字符串转换为IPAddress 实例。 |
- (2) 调用TcpListener类的Start()方法。该方法可以使TcpListenerduixiang开始监听连接请求。
- (3) 方法AcceptSock()可以接收来自客户端的连接请求。该方法返回一个Socket类的对象,该对象是实现与客户端通信的套接字;
- (4) 调用Sockets类的Receive和Send方法来通信;
- (5) 使用Socket对象的Close()方法关闭连接;使用TcpListener类的Stop()方法关闭侦听器。
客户端
五个步骤:
(1) 创建一个TcpClient类的对象
| TcpClient() | 初始化 TcpClient 类的新实例。 |
|---|---|
| TcpClient(AddressFamily) | 使用指定的族初始化 TcpClient 类的新实例。 |
| TcpClient(IPEndPoint) | 初始化 TcpClient 类的新实例,并将其绑定到指定的本地终结点。 |
| TcpClient(String, Int32) | 初始化 TcpClient 类的新实例并连接到指定主机上的指定端口。 |
(2) 使用TcpClient类的Connect方法建立与服务器的连接。
疑惑:这里的Connect方法同样可以实现与指定IP和端口的服务器连接,那TcpClient类的构建函数中就没必要指定IP和端口了
(实际上,在下面的例子中,创建TcpClient对象时,并没有传参数)
(3) 使用TcpClient的GetStream()方法来得到一个用于发送和接收数据的NetworkStream对象。
NetworkStream的WriteByte和Write方法分别能够用于向服务器输出单字节或一组字节;ReadByte和Read方法分别能从服务器读取单字节或一组字节;
public override void Write(byte[] buffer, int offset, int size)
参数解析:
| buffer |
类型 Byte 的数组,该数组包含要写入 NetworkStream 的数据。 |
|---|---|
| offset | buffer 中开始写入数据的位置,一般取0; |
| size |
要写入 NetworkStream 的字节数,取值为buffer.Length-offset。 (当offset=0时,size=buffer.Length) |
Read()方法类似,不单做解释;
(4) 使用NetworkStream对象的WriteByte,Write,ReadByte,Read方法与服务器进行通信;
(5) 调用NetworkStream的Close方法来关闭连接;接着调用TcpClient类的Close()方法来终止TCP连接。
注意事项:
无论是Socket类的Receive()或Send()方法,还是NetworkStream的Read()或Write()方法,都是直接读写Byte[]类型的变量,而我们习惯使用string类型的变量
使用如下转换:
字节数组到字符串:
Encoding.ASCII.GetString()public virtual string GetString(byte[] bytes)
输入byte[]类型变量,输出string类型变量;
字符串到字节数组:
Encoding.ASCII.GetBytes()public virtual byte[] GetBytes(string s)
代码实现
服务端
namespace tcplistenerTest{class Program{static void Main(string[] args){string srvIP = "127.0.0.1";IPAddress srvAddr = IPAddress.Parse(srvIP);int nPort = 2030;//创建并绑定套接字TcpListener srvLstner = new TcpListener(srvAddr, nPort);//开始监听try{srvLstner.Start(5);}catch (SocketException e){Console.WriteLine(e.Message);srvLstner.Stop();Console.ReadLine();return;}//接受客户端连接请求while (true){//接收连接请求Socket remoteSock = srvLstner.AcceptSocket();//显示客户端发送过来的消息Byte[] recvBuf = new Byte[128];try{remoteSock.Receive(recvBuf);}catch (SocketException e){Console.WriteLine(e.Message);break;}string recvMsg = Encoding.ASCII.GetString(recvBuf);Console.WriteLine(recvMsg);remoteSock.Close();}srvLstner.Stop();}}}
客户端
namespace TcpClientTest{class Program{static void Main(string[] args){TcpClient tcpClient = new TcpClient();IPAddress srvAddr = IPAddress.Parse("127.0.0.1");int nPort = 2030;//连接到服务器try{tcpClient.Connect(srvAddr, nPort);}catch (SocketException e){Console.WriteLine(e.Message);tcpClient.Close();Console.ReadLine();return;}NetworkStream sockStream = tcpClient.GetStream();string sendMsg = "hello, srver! This is client A";Byte[] sendBuf = Encoding.ASCII.GetBytes(sendMsg);try{sockStream.Write(sendBuf, 0, sendBuf.Length);}catch (SocketException e){Console.WriteLine(e.Message);sockStream.Close();tcpClient.Close();Console.ReadLine();return;}Console.WriteLine("成功向服务器发送消息:{0}\n", sendMsg);sockStream.Close();tcpClient.Close();Console.ReadLine();}}}
