TCP协议是c#.net日常开发经常用到的技术,一般伴随着消息收发交互、文件传输等功能;本文介绍了c#如何使用TCP实现消息收发、文件收发功能。示例基于WatsonTcp
,此类库是一个开源免费的库,原生TcpListener
以后有需要再写例子吧。最后需要注意的是,由于WatsonTcp对交互数据进行过包装,须使用WatsonTcpServer(服务端) 和WatsonTcpClient(客户端)进行数据交互,无法与其他原生TCP客户端/服务端数据交互。
WatsonTcp开源地址:https://github.com/jchristn/WatsonTcp
示例程序地址:https://github.com/zonevg/WatsonTcpExample
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("请先选中客户端");
}
}
}
}
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 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;
}
}
}
3 条评论
博主方便价格微信吗,想咨询下WatsonTcp的使用
请问断开方法ClientDisconnected有效吗?MessageReceived能收到客户端发送的消息吗?
ClientDisconnected是断开事件,当服务端/客户端断开时都会有事件通知的,MessageReceived可以接受到客户端消息;我上面分别贴了客户端和服务端代码复制过去就能用