侧边栏壁纸
  • 累计撰写 62 篇文章
  • 累计收到 17 条评论
C#

TCP/IP简单示例文件发送(WatsonTcp)

一缕清风
2021-03-01 / 4 评论 / 25 阅读 / 正在检测是否收录...

简介

TCP协议是日常开发经常用到的技术,一般伴随着消息收发交互、文件传输等功能;本文介绍了如何使用TCP实现消息收发、文件收发功能。示例基于WatsonTcp,此类库是一个开源免费的库,原生TcpListener以后有需要再写例子吧。

WatsonTcp开源地址:https://github.com/jchristn/WatsonTcp

示例程序地址:https://github.com/zonevg/WatsonTcpExample

由于WatsonTcp对交互数据进行过包装,必须使用WatsonTcpServer(服务端) 和WatsonTcpClient(客户端)进行数据交互,无法与其他原生TCP客户端/服务端数据交互,望知悉。

tcp测试工具

tcp测试工具

服务端代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WatsonTcp;

namespace TcpServer
{
    public partial class FrmServer : Form
    {
        public FrmServer()
        {
            InitializeComponent();
        }
        private WatsonTcp.WatsonTcpServer server;
        private void btn_link_Click(object sender, EventArgs e)
        {
            if (btn_link.Text == "启动")
            {
                server = new WatsonTcp.WatsonTcpServer($"{txt_ip.Text.Replace(" ", "")}", int.Parse(txt_port.Text));
                server.Events.ClientConnected += OnConnected;
                server.Events.MessageReceived += OnDataReceived;
                server.Events.ClientDisconnected += OnDisconnected;
                btn_link.Text = "停止";
                server.Start();
            }
            else
            {
                btn_link.Text = "启动";
                server.DisconnectClients(MessageStatus.Normal);
                server.Dispose();
            }
        }
        private void OnDisconnected(object sender, DisconnectionEventArgs e)
        {
            this.BeginInvoke((Action)delegate
            {
                cbo_client.Items.Remove(e.IpPort);
            });
            ShowLog($"客户端断开连接,原因:{e.Reason}");
        }

        private void OnDataReceived(object sender, MessageReceivedEventArgs e)
        {
            if (e.Metadata?.ContainsKey("file") ?? false)
            {
                string path = $"{ AppDomain.CurrentDomain.BaseDirectory }\\{ DateTime.Now.ToString("yyyyMMddHHmmssfff")}{e.Metadata["file"]}";

                using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite))
                {
                    fs.Write(e.Data, 0, e.Data.Length);
                    fs.Flush();
                    fs.Close();
                    fs.Dispose();
                }
                ShowLog($"收到文件,路径{path}");
            }
            else
            {
                ShowLog(Encoding.UTF8.GetString(e.Data));
            }
        }

        private void OnConnected(object sender, ConnectionEventArgs e)
        {
            this.BeginInvoke((Action)delegate
            {
                cbo_client.Items.Add(e.IpPort);
            });
            ShowLog("客户端连接成功");
        }

        private void ShowLog(string msg)
        {
            this.BeginInvoke((Action)delegate
            {
                ri_log.Text += $"{DateTime.Now.ToString("yyyyy-MM-dd HH:mm:ss")} {msg}\r\n";
            });
        }

        private void FrmServer_Load(object sender, EventArgs e)
        {

        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            if (cbo_client.Text != "")
            {
                server.Send(cbo_client.Text, txt_msg.Text);
                txt_msg.Text = string.Empty;
            }
            else
            {
                MessageBox.Show("请先选中客户端");
            }
        }

        private void btn_sendfile_Click(object sender, EventArgs e)
        {
            if (cbo_client.Text != "")
            {
                FileDialog file = new OpenFileDialog();
                if (file.ShowDialog() == DialogResult.OK)
                {
                    using (FileStream fs = new FileStream(file.FileName, FileMode.Open, FileAccess.Read))
                    {
                        Dictionary<object, object> dict = new Dictionary<object, object>();
                        dict.Add("file", Path.GetExtension(file.FileName));
                        MemoryStream ms = new MemoryStream();
                        fs.CopyTo(ms);
                        server.SendAsync(cbo_client.Text, ms.GetBuffer(), dict);
                    }
                }
            }
            else
            {
                MessageBox.Show("请先选中客户端");
            }
        }
    }
}

客户端代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WatsonTcp;

namespace TcpClient
{
    public partial class FrmClient : Form
    {
        public FrmClient()
        {
            InitializeComponent();
        }

        private WatsonTcp.WatsonTcpClient client;
        private void btn_link_Click(object sender, EventArgs e)
        {
            if (btn_link.Text == "连接")
            {
                client = new WatsonTcp.WatsonTcpClient($"{txt_ip.Text.Replace(" ", "")}", int.Parse(txt_port.Text));
                client.Events.ServerConnected += OnConnected;
                client.Events.MessageReceived += OnDataReceived;
                client.Events.ServerDisconnected += OnDisconnected;
                client.Connect();
                btn_link.Text = "断开";
            }
            else
            {
                btn_link.Text = "连接";
                client.Disconnect();
            }
        }

        private void OnDisconnected(object sender, DisconnectionEventArgs e)
        {
            ShowLog($"断开连接,原因:{e.Reason}");
        }

        private void OnDataReceived(object sender, MessageReceivedEventArgs e)
        {
            if (e.Metadata?.ContainsKey("file") ?? false)
            {
                string path = $"{ AppDomain.CurrentDomain.BaseDirectory }\\{ DateTime.Now.ToString("yyyyMMddHHmmssfff")}{e.Metadata["file"]}";

                using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite))
                {
                    fs.Write(e.Data, 0, e.Data.Length);
                    fs.Flush();
                    fs.Close();
                    fs.Dispose();
                }
                ShowLog($"收到文件,路径{path}");
            }
            else
            {
                ShowLog(Encoding.UTF8.GetString(e.Data));
            }
        }

        private void OnConnected(object sender, ConnectionEventArgs e)
        {
            ShowLog("连接成功");
        }

        private void ShowLog(string msg)
        {
            this.BeginInvoke((Action)delegate
            {
                ri_log.Text = ri_log.Text.Insert(0, $"{DateTime.Now.ToString("yyyyy-MM-dd HH:mm:ss")} {msg}\r\n");
            });
        }

        private void btn_sendfile_Click(object sender, EventArgs e)
        {
            FileDialog file = new OpenFileDialog();
            if (file.ShowDialog() == DialogResult.OK)
            {
                using (FileStream fs = new FileStream(file.FileName, FileMode.Open, FileAccess.Read))
                {
                    Dictionary<object, object> dict = new Dictionary<object, object>();
                    dict.Add("file", Path.GetExtension(file.FileName));
                    MemoryStream ms = new MemoryStream();
                    fs.CopyTo(ms);
                    client.SendAsync(ms.GetBuffer(), dict);
                }
            }
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            client.Send(txt_msg.Text);
            txt_msg.Text = string.Empty;
        }
    }
}
0

评论 (4)

取消
  1. 头像
    飘影
    Windows 10 · FireFox

    博主方便价格微信吗,想咨询下WatsonTcp的使用

    回复
    1. 头像
      一缕清风 作者
      Windows 10 · Google Chrome
      @ 飘影

      qq:1315336328 微信:duodio

      回复
  2. 头像
    飘影
    Windows 10 · FireFox

    请问断开方法ClientDisconnected有效吗?MessageReceived能收到客户端发送的消息吗?

    回复
    1. 头像
      一缕清风 作者
      Android · Google Chrome
      @ 飘影

      ClientDisconnected是断开事件,当服务端/客户端断开时都会有事件通知的,MessageReceived可以接受到客户端消息;我上面分别贴了客户端和服务端代码复制过去就能用

      回复