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

服务器 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);        }    }‍

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

也许您对下面的内容还感兴趣: