TCP/IP协议——使用TcpListener和Tcpclient类实现通信

avatar
作者
筋斗云
阅读量:0

目录

TcpListener和TcpClient

TcpListener和TcpClient的使用

连接到服务器

创建服务器套接字

接收服务器连接

创建 `NetworkStream`​​ 以发送和接收数据

关闭连接

使用TcpListener搭建Tcp服务器

TcpClient用于客户端和服务器连接


TcpListener和TcpClient

在C#中实现TCP通信,你可以使用 System,Net.Sockets 命名空间中的 TcpListener 和
Tcpclient 类。

若要使用传输控制协议(TCP),有两个选项:使用 Socket以获得最大控制和性能,或使用 Icpclient 和IcpListener 帮助程序类。Icpclien 和 IcpListener 是在System.Net.Sockets.Socket 类的基础上建立的,并负责传输数据的详细信息以便于使用。

TcpListener和TcpClient的使用

连接到服务器

​`TcpClient`​ 中的所有 `Connect`​、`ConnectAsync`​、`BeginConnect`​ 和 `EndConnect`​ 重载在功能上都等效于相应的 `Socket`​ 方法。

请考虑以下 TCP 客户端代码:

    var client = new TcpClient();     client.Connect("www.example.com", 80);

上述 `TcpClient`​ 代码等效于以下套接字代码:

    var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);     socket.Connect("www.example.com", 80);

创建服务器套接字

就像与原始 `Socket`​ 对应项功能等效的 `TcpClient`​ 实例一样,本部分将 `TcpListener`​ 构造函数映射到其相应的套接字代码。 要考虑的第一个构造函数是 `TcpListener(IPAddress localaddr, int port)`​。

var listener = new TcpListener(IPAddress.Loopback, 5000);

前面的 TCP 侦听器代码在功能上等效于下面的套接字代码:

var ep = new IPEndPoint(IPAddress.Loopback, 5000); var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

开始侦听服务器

Start()方法是组合 socket 的 Bind 和 Listen() 功能的包装器

var listener = new TcpListener(IPAddress.Loopback, 5000); listener.Start(10);

前面的 TCP 侦听器代码在功能上等效于下面的套接字代码:

var endPoint = new IPEndPoint(IPAddress.Loopback, 5000); var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.Bind(endPoint); socket.Listen(10);

接收服务器连接

在后台,传入的TCP 连接在接受时始终会创建新的套接字。 TcpListener 可以直接接受 socket实例(通过 Acceptsocketl)或 AceptsocketAsymc),也可以接受 IcpClient(通过AcceptTcpClient()和AcceptTcpClientAsync())。

var listener = new TcpListener(IPAddress.Loopback, 5000); var acceptedSocket = await listener.AcceptSocketAsync();

前面的 TCP 侦听器代码在功能上等效于下面的套接字代码:

var endPoint = new IPEndPoint(IPAddress.Loopback, 5000); var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); var acceptedSocket = await socket.AcceptAsync();

创建 `NetworkStream`​​ 以发送和接收数据

使用 Tcpclient 时,需要使用 Getstream()方法实例化NetworkStream,以便能够发送和接收数据。使用socket 时,必须手动创建 Networkstream

var client = new TcpClient(); NetworkStream stream = client.GetStream();

等效于以下套接字代码:

var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); var stream = new NetworkStream(socket, ownsSocket: true);

如果代码不需要使用 stream 实例,则可以直接依赖 scket 的发送/接收方法(Send、SendAsync、Receive和 ReceveAsync),而不是创建 Networkstream.

关闭连接

使用 `TcpClient`​ 时,需要使用 Close()方法关闭连接,

var client = new TcpClient(); client.Close();

使用TcpListener搭建Tcp服务器

    TcpListener listener;     Dictionary<string, TcpClient> clientList = new Dictionary<string, TcpClient>();          private void button1_Click(object sender, EventArgs e)     {         // 按钮状态         openBtn.Enabled = false;         closeBtn.Enabled = true;              // 1.创建监听对象         listener = new TcpListener(IPAddress.Any, 3030);         // 2.开始监听(backlog:链接最大的挂起数)         listener.Start(100);         startListener(listener);          }     private void startListener(TcpListener lis)     {         // 3.等待链接(接收挂起的连接请求)         Task.Run(() =>         {             while (true)             {                 try                 {                     TcpClient client = lis.AcceptTcpClient();                     string ip = client.Client.RemoteEndPoint.ToString(); // 获取连接客户的IP                     clientList.Add(ip, client);                     startReceive(client.GetStream(), ip);                     addRichTextBox($"{ip}已经连接到服务器");                 }                 catch (Exception ex)                 {                     lis.Stop();                     break;                 }             }         });     }     private void startReceive(NetworkStream stream, string ip)     {         Task.Run(() =>         {             while (true)             {                 try                 {                     byte[] buffer = new byte[1024];  // 大小按情况而定                     int length = stream.Read(buffer, 0, buffer.Length);  // 返回本次接收数据的字节数                     if (length == 0)                     {                         throw new Exception($"客户端{ip}断开连接");                     }                     else                     {                         string value = Encoding.Default.GetString(buffer, 0, length);                         addRichTextBox($"接收到{ip}发送的消息:{value}\r\n");                     }                 }                 catch                 {                     // 从字典中移除当前连接                     clientList.Remove(ip);                     addRichTextBox($"{ip}连接已断开\r\n");                     break;                 }             }         });     }     // 发送信息给客户端     private void sendBtn_Click(object sender, EventArgs e)     {         byte[] bytes = Encoding.Default.GetBytes(msgTextbox.Text);         // 循环所有的客户端发送数据(也可以根据IP选择给谁发送)         foreach (var item in clientList)         {             item.Value.GetStream().Write(bytes, 0, bytes.Length);         }     }     // 关闭按钮点击     private void closeBtn_Click(object sender, EventArgs e)     {         // 控制按钮状态         closeBtn.Enabled = false;         openBtn.Enabled = true;              foreach (var item in clientList)         {             TcpClient client = item.Value;             client.Close();         }         listener.Stop();     }     private void addRichTextBox(string text)     {         richTextBox1.Invoke(new Action(() =>         {             richTextBox1.AppendText(text);             // 让rich滚动到最下面             richTextBox1.SelectionStart = richTextBox1.Text.Length;             richTextBox1.ScrollToCaret();         }));     }

TcpClient用于客户端和服务器连接

简单代码示例如下

    private TcpClient tcpClient;     private void button1_Click(object sender, EventArgs e)     {         // 1.创建客户端对象         tcpClient = new TcpClient();         // 2.开始链接         tcpClient.Connect(IPAddress.Parse("127.0.0.1"),3030);         // 3.获取数据流 Stream(读read 和 写write)         NetworkStream stream = tcpClient.GetStream();         // 4. 开启分线程         Thread thread = new Thread(ClientThread);         thread.Start(stream);     }     // 开分线程,收发消息     private void ClientThread(object obj)     {         NetworkStream stream = obj as NetworkStream;         while (true)         {             // 5.向服务器发送消息(自定义一个带输入框的对话框)             string info = "张三发送的消息";             byte[] bytes = Encoding.UTF8.GetBytes(info);             stream.Write(bytes,0,bytes.Length);                  // 6.接收来自服务器的消息             byte[] buffer = new byte[1024];             int length = stream.Read(buffer,0,buffer.Length);             string msg = Encoding.UTF8.GetString(buffer,0,length);             MessageBox.Show(msg);         }     }  ‍

本篇文章部分参考于网络,如有侵权请联系本人删除!!!

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!