在C#中,实现了很多对Windows API的封装,在套接字通信方面也是如此。下面是一个TCP网络通信的简单实例,因为自己初学C#,记下来学习

使用名字空间:

  1. using System.Net;
  2. 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方法分别能从服务器读取单字节或一组字节;

  1. 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类型的变量

使用如下转换:

字节数组到字符串:

  1. Encoding.ASCII.GetString()
  2. public virtual string GetString(byte[] bytes)

输入byte[]类型变量,输出string类型变量;

字符串到字节数组:

  1. Encoding.ASCII.GetBytes()
  2. public virtual byte[] GetBytes(string s)

输入string类型变量,输出byte[]类型变量;

代码实现

服务端

  1. namespace tcplistenerTest
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. string srvIP = "127.0.0.1";
  8. IPAddress srvAddr = IPAddress.Parse(srvIP);
  9. int nPort = 2030;
  10. //创建并绑定套接字
  11. TcpListener srvLstner = new TcpListener(srvAddr, nPort);
  12. //开始监听
  13. try
  14. {
  15. srvLstner.Start(5);
  16. }
  17. catch (SocketException e)
  18. {
  19. Console.WriteLine(e.Message);
  20. srvLstner.Stop();
  21. Console.ReadLine();
  22. return;
  23. }
  24. //接受客户端连接请求
  25. while (true)
  26. {
  27. //接收连接请求
  28. Socket remoteSock = srvLstner.AcceptSocket();
  29. //显示客户端发送过来的消息
  30. Byte[] recvBuf = new Byte[128];
  31. try
  32. {
  33. remoteSock.Receive(recvBuf);
  34. }
  35. catch (SocketException e)
  36. {
  37. Console.WriteLine(e.Message);
  38. break;
  39. }
  40. string recvMsg = Encoding.ASCII.GetString(recvBuf);
  41. Console.WriteLine(recvMsg);
  42. remoteSock.Close();
  43. }
  44. srvLstner.Stop();
  45. }
  46. }
  47. }

客户端

  1. namespace TcpClientTest
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. TcpClient tcpClient = new TcpClient();
  8. IPAddress srvAddr = IPAddress.Parse("127.0.0.1");
  9. int nPort = 2030;
  10. //连接到服务器
  11. try
  12. {
  13. tcpClient.Connect(srvAddr, nPort);
  14. }
  15. catch (SocketException e)
  16. {
  17. Console.WriteLine(e.Message);
  18. tcpClient.Close();
  19. Console.ReadLine();
  20. return;
  21. }
  22. NetworkStream sockStream = tcpClient.GetStream();
  23. string sendMsg = "hello, srver! This is client A";
  24. Byte[] sendBuf = Encoding.ASCII.GetBytes(sendMsg);
  25. try
  26. {
  27. sockStream.Write(sendBuf, 0, sendBuf.Length);
  28. }
  29. catch (SocketException e)
  30. {
  31. Console.WriteLine(e.Message);
  32. sockStream.Close();
  33. tcpClient.Close();
  34. Console.ReadLine();
  35. return;
  36. }
  37. Console.WriteLine("成功向服务器发送消息:{0}\n", sendMsg);
  38. sockStream.Close();
  39. tcpClient.Close();
  40. Console.ReadLine();
  41. }
  42. }
  43. }