阅读 218

C#实现Socket服务器及多客户端连接的方式

这篇文章介绍了C#实现Socket服务器及多客户端连接的方式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

服务端代码[控制台示例]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
static List<Socket> Sockets = new List<Socket>();
        static void Main(string[] args)
        {
            int port = 10;
            byte[] buffer = new byte[1024];
 
            IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);
            Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
 
            try
            {
                listener.Bind(localEP);
                listener.Listen(10);
                Console.WriteLine("等待客户端连接....");
                while (true) //该操作用于多个客户端连接
                {
                    Socket sc = listener.Accept();//接受一个连接
                    Sockets.Add(sc); //将连接的客户端, 添加到内存当中
                    Thread t = new Thread(new ThreadStart(() => ReceiveData(sc))); //开启当前Socket线程, 去执行获取数据的动作,与客户端通信
                    t.IsBackground = true;
                    t.Start();
                }
 
 
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.ReadLine();
        }
 
        public static void ReceiveData(Socket sc)
        {
            byte[] buffer = new byte[1024];
            Console.WriteLine("接受到了客户端:" + sc.RemoteEndPoint.ToString() + "连接....");
            //握手
            int length = sc.Receive(buffer);//接受客户端握手信息
            sc.Send(PackHandShakeData(GetSecKeyAccetp(buffer, length)));while (true)
            {
                try
                {
                    //接受客户端数据
                    Console.WriteLine("等待客户端数据....");
                    length = sc.Receive(buffer);//接受客户端信息
                    string clientMsg = AnalyticData(buffer, length);
                    Console.WriteLine("接受到客户端数据:" + clientMsg);
                    //发送数据
                    string sendMsg = "服务端返回信息:" + clientMsg;
                    sc.Send(PackData(sendMsg));
                }
                catch (Exception ex)
                {
                    Sockets.Remove(sc);  //如果接收的过程中,断开, 那么内存中移除当前Socket对象, 并且退出当前线程
                    Console.WriteLine("客户端已经断开连接!");
                    return;
                }
            }
        }

Socket 相关类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/// <summary>
      /// 打包握手信息
      /// </summary>
      /// <param name="secKeyAccept"></param>
      /// <returns></returns>
      private static byte[] PackHandShakeData(string secKeyAccept)
      {
          var responseBuilder = new StringBuilder();
          responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
          responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
          responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
          responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);
          return Encoding.UTF8.GetBytes(responseBuilder.ToString());
      }
 
      /// <summary>
      /// 生成Sec-WebSocket-Accept
      /// </summary>
      /// <param name="handShakeText">客户端握手信息</param>
      /// <returns>Sec-WebSocket-Accept</returns>
      private static string GetSecKeyAccetp(byte[] handShakeBytes, int bytesLength)
      {
          string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0, bytesLength);
          string key = string.Empty;
          Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n");
          Match m = r.Match(handShakeText);
          if (m.Groups.Count != 0)
          {
              key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$1").Trim();
          }
          byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
          return Convert.ToBase64String(encryptionString);
      }
 
      /// <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;
      }

客户端连接[网页测试]

WebSocket客户端示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSockets客户端示例</title>
</head>
<script>
var webSocket;
function connect()
{
    try
    {
        var readyState = new Array("正在连接","已建立连接","正在关闭连接","已关闭连接");
        var host = "ws://localhost:10";
        webSocket = new WebSocket(host);
        var message = document.getElementById("message");
        message.innerHTML +="<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
        webSocket.onopen = function()
        {
            message.innerHTML += "<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
        }
        webSocket.onmessage = function(msg)
        {
            message.innerHTML +="<p>接收信息:" + msg.data + "</p>";
        }
        webSocket.onclose=function()
        {
            message.innerHTML +="<p>Socket状态:" + readyState[webSocket.readyState] + "</p>";
        }
    }
    catch(exception)
    {
        message.innerHTML += "<p>有错误发生</p>";
    }
}
function send()
{
    var text = document.getElementById("text").value;
    var message = document.getElementById("message");
    if(text == "")
    {
        message.innerHTML += "<p>请输入一些文字</p>";
        return ;
    }
    try
    {
        webSocket.send(text);
        message.innerHTML += "<p>发送数据:" +text + "</p>";
    }
    catch(exception)
    {
        message.innerHTML += "<p>发送数据出错</p>";
    }
    document.getElementById("text").value="";
}
function disconnect()
{
    webSocket.close();
}
</script>
<body>
<h1>WebSocket客户端示例</h1>
<div id="message"></div>
<p>请输入一些文字</p>
<input id="text" type="text">
<button id="connect" onClick="connect();">建立连接</button>
<button id="send" onClick="send();">发送数据</button>
<button id="disconnect" onClick="disconnect();">断开连接</button>
</body>
</html>

以上所述是小编给大家介绍的C#实现Socket服务器及多客户端连接的方式,希望对大家有所帮助。

原文链接:https://www.cnblogs.com/zh7791/p/11151787.html


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐