大家好,我是青空。
由于现在工作上,有很多socket交互的情况,自己在网上找了一些工具, 但是要么不好用,要么就是只能使用几天,就需要收费了。 青空就想着自己搞一个好了, 针对自己的应用场景,直接定制。
那就先上个图吧
已实现的功能
目前已经完成了第一个版本。功能点如下:
- 根据TCP/IP 协议链接到服务端
- 通过 ASCII、Hex 两种编码格式进行消息互通
- 格式化显示消息发送、接收数据
- 自动重发命令
- 记录命令发送历史
核心代码
在这个工具中,最核心的不过是在于,建立socket链接,然后进行消息的接收和发送。
建立socket的过程,先确定 TCP 服务端IP和端口是否准确,然后再通过 socket api 进行连接。建立连接之后,进行状态的改变,启动接收消息的线程。
var ipString = cbServerIp.Text.ToString().Trim();
var ipPort = cbServerPort.Text.ToString().Trim();
if (string.IsNullOrWhiteSpace(ipString) || string.IsNullOrWhiteSpace(ipPort))
{
MessageBox.Show("请先输入服务器IP和端口号");
return;
}
if (Connected == false)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IP = IPAddress.Parse(ipString);
port = Convert.ToInt32(ipPort);
remoteEndPoint = new IPEndPoint(IP, port);
try
{
socket.Connect(remoteEndPoint);
Connected = true;
btnConnect.Text = "断开服务器";
connectStatus.Text = "This socket is connected";
connectStatus.ForeColor = Color.Green;
}
catch (SocketException ex)
{
Connected = false;
btnConnect.Text = "连接服务器";
connectStatus.Text = "This socket is not connected";
connectStatus.ForeColor = Color.Red;
}
Thread thread = new Thread(ReceiveMsg);
thread.IsBackground = true;
thread.Start();
}
else
{
Connected = false;
btnConnect.Text = "连接服务器";
socket.Disconnect(false);
socket.Close();
connectStatus.Text = "This socket is not connected";
connectStatus.ForeColor = Color.Red;
}
接下来就介绍一下,我们是如何接收消息的,接收消息的过程我们是在循环遍历读取 socket 连接中的消息,然后展示到我们的接收区的文本框中。
while (Connected)
{
StringBuilder sb = new StringBuilder("[接收] ");
if (closeForm == false)
{
try
{
if (Connected == false)
{
return;
}
byte[] data = new byte[1024];
var n = socket.Receive(data);
if (n > 0)
{
byte[] buf = new byte[n];
Array.Copy(data, 0, buf, 0, n);
if (chbShowTime.Checked)
{
sb.Append("[");
var now = DateTime.Now;
sb.Append(now.ToString("yyyy-MM-dd"));
sb.Append(" ");
sb.Append(now.ToString("HH:mm:ss:fff"));
sb.Append("] ");
}
if (rdbRevASCII.Checked)
{
sb.Append(Encoding.ASCII.GetString(buf));
}
if (rdbRevHex.Checked)
{
foreach (var b in buf)
{
sb.Append(b.ToString("X2") + " ");
}
}
if (chbNewLine.Checked)
{
sb.Append("\n");
}
}
}
catch (SocketException ex)
{
Connected = false;
btnConnect.Text = "连接服务器";
MessageBox.Show("与服务器断开 " + ex.Message, "错误提示");
}
catch (Exception ex)
{
Connected = false;
btnConnect.Text = "连接服务器";
showMsg("接收数据异常,可能已经断联");
}
}
showMsg(sb.ToString());
}
通常我们会把UI线程和业务线程给分离开,这是由于如果不进行分离的话,如果业务线程卡住的话, UI线程会出现未响应的状态。那我们为了能够在UI线程显示数据,我们就需要通过委托调用的方式能够让UI进行正常运行, 代码如下。
if (this.InvokeRequired)
{
ReceiveMsgDele receiveMsgDele = new ReceiveMsgDele(showMsg);
rtbRevText.Invoke(receiveMsgDele, new object[] { msg });
}
else
{
rtbRevText.AppendText(msg);
}
下一步
在目前的功能基础上,增加定制化的功能, 比如持久化消息的发送历史,批量发送命令,有交互性的重复发送命令等。
总结
今天青空给大家介绍了最近自己开发的 TCP/IP 的调试工具,实现了互通消息的功能, 更多其他的功能在持续开发中,对这个感兴趣的话,可以联系我。暂时不对齐进行开源,等到代码完善了之后再考虑开源的事项。