1.背景
需要做一个C端的工厂设备运行情况的大屏展示功能,因为设备的情况是实时数据,所以需要运用到Socket,在网上找了一下相关的开源组件,比如SuperSocket,FastSocket等,后来找到HP-Socket,觉得HP-Socket是最简单易用的,真正的做到了拿来就用,无需了解Socket底层机制。
2.实现示例
2.1 Socket 服务端代码
using HPSocket.Sdk;
using HPSocket;
using HPSocket.Tcp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Collections;
namespace WebApi.Controllers
{
public class ValuesController : ApiController
{
TcpServer hpServer = new TcpServer();
bool tcp1State = false;
public IntPtr commonconnId;
/// <summary>
/// 添加监听事件.
/// </summary>
[HttpGet]
[Route("api/values/StartServe")]
public string StartServe()
{
hpServer.OnPrepareListen += OnPrepareListen;
hpServer.OnAccept += OnAccept; //连接事件
hpServer.OnClose += OnClose; //断开连接事件
hpServer.OnReceive += OnReceive;// 接收数据
hpServer.OnSend += OnSend;// 发送数据
hpServer.Address = "127.0.0.1";// 设置服务端IP
hpServer.Port = Convert.ToUInt16(4000);// 设置端口
hpServer.SendPolicy = SendPolicy.Pack;
hpServer.Start();
// 发送数据
return "服务端已开启并监听";
}
/// <summary>
/// 服务端往客户端发送消息
/// </summary>
[HttpGet]
[Route("api/values/SendMessage")]
public string SendMessage()
{
string ss = "测试一下啊啊啊啊";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(ss);
uint ConnectionCount = hpServer.ConnectionCount;
var ConnectionIds = hpServer.GetAllConnectionIds();
if (ConnectionIds.Count != 0)
{
commonconnId = ConnectionIds[0];
}
try
{
hpServer.ResumeReceive(commonconnId);
hpServer.Send(commonconnId, bytes, ss.Length);
hpServer.ResumeReceive(commonconnId);
}
catch
(Exception ex)
{ }
return "发送消息";
}
/// <summary>
/// 停止服务
/// </summary>
[HttpGet]
[Route("api/values/StopServe")]
public string StopServe()
{
hpServer = new TcpServer();
hpServer.Address = "127.0.0.1";// 设置服务端IP
hpServer.Port = Convert.ToUInt16(4000);// 设置端口
hpServer.SendPolicy = SendPolicy.Direct;
hpServer.Stop(); // 关闭通信
return "服务端已关闭通信";
}
/// <summary>
/// 打开监听
/// </summary>
/// <param name="sender"></param>
/// <param name="listen"></param>
/// <returns></returns>
private HandleResult OnPrepareListen(IServer sender, IntPtr listen)
{
return HandleResult.Ok;
}
/// <summary>
/// 连接事件
/// </summary>
/// <param name="sender"></param>
/// <param name="connId"></param>
/// <param name="client"></param>
/// <returns></returns>
private HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr client)
{
// 获取客户端地址
if (!sender.GetRemoteAddress(connId, out var ip, out var port))
{
return HandleResult.Error;
}
commonconnId = connId;
return HandleResult.Ok;
}
/// <summary>
/// 服务器收到数据
/// </summary>
/// <param name="sender"></param>
/// <param name="connId"></param>
/// <param name="data"></param>
/// <returns></returns>
private HandleResult OnReceive(IServer sender, IntPtr connId, byte[] data)
{
try
{
string str = System.Text.Encoding.UTF8.GetString(data);
return HandleResult.Ok;
}
catch (Exception)
{
return HandleResult.Ignore;
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="sender"></param>
/// <param name="connId"></param>
/// <param name="data"></param>
/// <returns></returns>
private HandleResult OnSend(IServer sender, IntPtr connId, byte[] data)
{
try
{
return HandleResult.Ok;
}
catch (Exception)
{
return HandleResult.Ignore;
}
}
/// <summary>
/// 服务器关闭连接
/// </summary>
/// <param name="sender"></param>
/// <param name="connId"></param>
/// <param name="socketOperation"></param>
/// <param name="errorCode"></param>
/// <returns></returns>
private HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation socketOperation, int errorCode)
{
return HandleResult.Error;
}
/// <summary>
/// 服务器关闭
/// </summary>
/// <param name="sender"></param>
/// <returns></returns>
private HandleResult OnShutdown(IServer sender)
{
return HandleResult.Ok;
}
}
}
2.2 Socket 客户端代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HPSocket;
using HPSocket.Sdk;
using HPSocket.Tcp;
using HPSocket.WebSocket;
namespace WinFormsApp1
{
public partial class Form2 : Form
{
TcpClient hpClient = new TcpClient();
bool tcp1State = false;
public Form2()
{
InitializeComponent();
// ClientPrepareConnectEventHandler
hpClient.OnPrepareConnect += OnPrepareConnect; // 链接前
hpClient.OnConnect += OnConnect; // 链接成功后
hpClient.OnSend += OnSend; // 发送消息
hpClient.OnReceive += OnReceive; // 接受到消息后
hpClient.OnClose += OnClose; // 链接关闭后
hpClient.Address = "***.**.**.**"; // 服务端的Ip
hpClient.Port = 4000; // 服务端监听的端口
hpClient.BindAddress = "***.**.**.***"; // 客户端本机的ip
hpClient.BindPort = 7983; // 客户端本机的端口
//Test();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public HandleResult OnPrepareConnect(IClient sender, IntPtr socket)
{
return HandleResult.Ok;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public HandleResult OnConnect(IClient sender)
{
return HandleResult.Ok;
}
/// <summary>
/// 消息发送后
/// </summary>
/// <param name="sender"></param>
/// <returns></returns>
public HandleResult OnSend(IClient sender, byte[] data)
{
return HandleResult.Ok;
}
public HandleResult OnReceive(IClient sender, byte[] data)
{
var ss = "111";
return HandleResult.Ok;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="data"></param>
/// <returns></returns>
public HandleResult OnClose(IClient sender, SocketOperation socketOperation, int errorCode)
{
return HandleResult.Ok;
}
private void button1_Click(object sender, EventArgs e)
{
string ss = "客户端测试一下啊啊啊啊";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(ss);
var result = hpClient.Send(bytes, bytes.Length);
}
private void button2_Click(object sender, EventArgs e)
{
bool ConnectResult = hpClient.Connect();
hpClient.ConnectionTimeout = 1000 * 1000;
hpClient.KeepAliveInterval = 10;
hpClient.KeepAliveTime = 1000 * 5;
hpClient.PauseReceive = ReceiveState.Resume;
var ss = hpClient.ConnectionId;
var ss1 = hpClient.ErrorCode;
var ss2 = hpClient.ErrorMessage;
this.textBox1.Text = hpClient.IsConnected == true ? "连接" : "未连接";
}
private void button3_Click(object sender, EventArgs e)
{
this.textBox1.Text = hpClient.IsConnected == true ? "连接" : "未连接";
this.textBox1.Text += hpClient.HasStarted == true ? "启动" : "未启动";
this.textBox1.Text += hpClient.State.ToString();
}
}
}
3 注意点
1.服务端和客户端监听的服务端端口要一致。监听的端口并不是服务端服务运行的端口,可以自己制定一个监听端口,客户端绑定至本地的端口也并非是监听的端口号。