C#起一个Socket服务,js连接,当C#对js消息进行解析的时候出现中文乱码问题,直接上上代码:
private static SocketHelper _instance;
public static SocketHelper Instance
{
get
{
if (_instance == null)
_instance = new SocketHelper();
return _instance;
}
}
Socket clientSocket;
Socket _clientSocket;
Thread listenThread;
int _port = 0;
public SocketHelper()
{
}
public void InitSocket(int port)
{
_port = port;
listenThread = new Thread(websocketListen);
listenThread.IsBackground = true;
listenThread.Start();
}
private void websocketListen()
{
IPAddress ip = IPAddress.Parse("0.0.0.0");
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Bind(new IPEndPoint(ip, _port)); //绑定IP地址:端口
clientSocket.Listen(10); //设定最多10个排队连接请求
_log.Info($"socket服务 启动监听成功,地址:{clientSocket.LocalEndPoint.ToString()}");
// 监听多个客户端连接
while (true)
{
_clientSocket = clientSocket.Accept();
_log.Info($"socket服务 收到客户端连接,地址:{_clientSocket.RemoteEndPoint}");
Console.WriteLine($"收到客户端连接,地址:{_clientSocket.RemoteEndPoint}");
//接收客户端发来的HTTP-Header消息
byte[] bytes = new byte[1024];
int len = _clientSocket.Receive(bytes);
string strMessage = Encoding.UTF8.GetString(bytes, 0, len);
Console.WriteLine(strMessage);
//获取Sec-WebSocket-Key,为握手做准备
string[] strings = strMessage.Split('\n');
string strSecWebSocketKey = "";
foreach (var item in strings)
{
string[] strings1 = item.Split(':');
if (strings1[0] == "Sec-WebSocket-Key")
{
strSecWebSocketKey = strings1[1].Trim();
}
}
//生成服务端Sec-WebSocket-Accept,迎合客户端的握手请求
byte[] secKeyBytes = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(strSecWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
string secKey = Convert.ToBase64String(secKeyBytes);
// 发送给客户端完成握手(会触发Websocket的open()回调函数),针对websocket必须使用以下header
string strHeader = "";
strHeader += "HTTP/1.1 101 Switching Protocols" + Environment.NewLine;
strHeader += "Upgrade: websocket" + Environment.NewLine;
strHeader += "Connection: Upgrade" + Environment.NewLine;
strHeader += "Sec-WebSocket-Accept: " + secKey + Environment.NewLine + Environment.NewLine;
_clientSocket.Send(Encoding.UTF8.GetBytes(strHeader));
//string remoteFileUrl = null;
bool clientClose = false;
// 循环接收websocket发来的消息实现双方交流
while (!clientClose)
{
//接收客户端发来的消息
byte[] bytes2 = new byte[1024];
int len2 = _clientSocket.Receive(bytes2);
string strMessage2 = AnalyticData(bytes2, len2);
try
{
if (len2 == 0)
break;
var msgData = JsonConvert.DeserializeObject<MsgData>(strMessage2);
if (msgData != null)
{
Messenger.Default.Send(msgData.type, "SocketMsg");
}
}
catch (Exception ex)
{
Console.WriteLine("处理web发来的socket消息异常:" + ex.Message);
}
}
}
}
public void SendMessage(string msg)
{
if (msg == string.Empty)
return;
try
{
_log.Info($"socket服务 即将发送socket消息,内容:{msg}");
_clientSocket?.Send(PackData(msg));
}
catch (Exception ex)
{
_log.Error($"socket服务 发送消息异常,发送内容:{msg},异常信息:{ex.Message}");
}
}
/// <summary>
/// 解析客户端数据包,防止乱码
/// </summary>
/// <param name="recBytes">服务器接收的数据包</param>
/// <param name="recByteLength">有效数据长度</param>
/// <returns></returns>
private static string AnalyticData(byte[] recBytes, int recByteLength)
{
if (recByteLength < 2) { return string.Empty; }
bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧
if (!fin)
{
return string.Empty;// 超过一帧暂不处理
}
bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码
if (!mask_flag)
{
return string.Empty;// 不包含掩码的暂不处理
}
int payload_len = recBytes[1] & 0x7F; // 数据长度
byte[] masks = new byte[4];
byte[] payload_data;
if (payload_len == 126)
{
Array.Copy(recBytes, 4, masks, 0, 4);
payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
payload_data = new byte[payload_len];
Array.Copy(recBytes, 8, payload_data, 0, payload_len);
}
else if (payload_len == 127)
{
Array.Copy(recBytes, 10, masks, 0, 4);
byte[] uInt64Bytes = new byte[8];
for (int i = 0; i < 8; i++)
{
uInt64Bytes[i] = recBytes[9 - i];
}
UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);
payload_data = new byte[len];
for (UInt64 i = 0; i < len; i++)
{
payload_data[i] = recBytes[i + 14];
}
}
else
{
Array.Copy(recBytes, 2, masks, 0, 4);
payload_data = new byte[payload_len];
Array.Copy(recBytes, 6, payload_data, 0, payload_len);
}
for (var i = 0; i < payload_len; i++)
{
payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
}
return Encoding.UTF8.GetString(payload_data);
}
/// <summary>
/// 打包服务器数据,防止乱码
/// </summary>
/// <param name="message">数据</param>
/// <returns>数据包</returns>
private static byte[] PackData(string message)
{
byte[] contentBytes = null;
byte[] temp = Encoding.UTF8.GetBytes(message);
if (temp.Length < 126)
{
contentBytes = new byte[temp.Length + 2];
contentBytes[0] = 0x81;
contentBytes[1] = (byte)temp.Length;
Array.Copy(temp, 0, contentBytes, 2, temp.Length);
}
else if (temp.Length < 0xFFFF)
{
contentBytes = new byte[temp.Length + 4];
contentBytes[0] = 0x81;
contentBytes[1] = 126;
contentBytes[2] = (byte)(temp.Length & 0xFF);
contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);
Array.Copy(temp, 0, contentBytes, 4, temp.Length);
}
else
{
// 暂不处理超长内容
}
return contentBytes;
}