C# socket异步 服务端
标签:stream remote start oba class replace app local temp
转自: http://blog.csdn.net/qq_20282263/article/details/54310737
1 private Dictionarystring, Session> SessionPool = new Dictionarystring, Session>();
2 private Dictionarystring, string> MsgPool = new Dictionarystring, string>();
3
4 #region 启动WebSocket服务
5 ///
6 /// 启动WebSocket服务
7 ///
8 public void start(int port)
9 {
10 Socket SockeServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
11 SockeServer.Bind(new IPEndPoint(IPAddress.Any, port));
12 SockeServer.Listen(20);
13 SockeServer.BeginAccept(new AsyncCallback(Accept), SockeServer);
14 Console.WriteLine("服务已启动");
15 Console.WriteLine("按任意键关闭服务");
16 Console.ReadLine();
17 }
18 #endregion
19
20 #region 处理客户端连接请求
21 ///
22 /// 处理客户端连接请求
23 ///
24 ///
25 private void Accept(IAsyncResult socket)
26 {
27 // 还原传入的原始套接字
28 Socket SockeServer = (Socket)socket.AsyncState;
29 // 在原始套接字上调用EndAccept方法,返回新的套接字
30 Socket SockeClient = SockeServer.EndAccept(socket);
31 byte[] buffer = new byte[4096];
32 try
33 {
34 //接收客户端的数据
35 SockeClient.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Recieve), SockeClient);
36 //保存登录的客户端
37 Session session = new Session();
38 session.SockeClient = SockeClient;
39 session.IP = SockeClient.RemoteEndPoint.ToString();
40 session.buffer = buffer;
41 lock (SessionPool)
42 {
43 if (SessionPool.ContainsKey(session.IP))
44 {
45 this.SessionPool.Remove(session.IP);
46 }
47 this.SessionPool.Add(session.IP, session);
48 }
49 //准备接受下一个客户端
50 SockeServer.BeginAccept(new AsyncCallback(Accept), SockeServer);
51 Console.WriteLine(string.Format("Client {0} connected", SockeClient.RemoteEndPoint));
52 }
53 catch (Exception ex)
54 {
55 Console.WriteLine("Error : " + ex.ToString());
56 }
57 }
58 #endregion
59
60 #region 处理接收的数据
61 ///
62 /// 处理接受的数据
63 ///
64 ///
65 private void Recieve(IAsyncResult socket)
66 {
67 Socket SockeClient = (Socket)socket.AsyncState;
68 string IP = SockeClient.RemoteEndPoint.ToString();
69 if (SockeClient == null || !SessionPool.ContainsKey(IP))
70 {
71 return;
72 }
73 try
74 {
75 int length = SockeClient.EndReceive(socket);
76 byte[] buffer = SessionPool[IP].buffer;
77 SockeClient.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Recieve), SockeClient);
78 string msg = Encoding.UTF8.GetString(buffer, 0, length);
79 // websocket建立连接的时候,除了TCP连接的三次握手,websocket协议中客户端与服务器想建立连接需要一次额外的握手动作
80 if (msg.Contains("Sec-WebSocket-Key"))
81 {
82 SockeClient.Send(PackageHandShakeData(buffer, length));
83 SessionPool[IP].isWeb = true;
84 return;
85 }
86 if (SessionPool[IP].isWeb)
87 {
88 msg = AnalyzeClientData(buffer, length);
89 }
90 byte[] msgBuffer = PackageServerData(msg);
91 foreach (Session se in SessionPool.Values)
92 {
93 se.SockeClient.Send(msgBuffer, msgBuffer.Length, SocketFlags.None);
94 }
95 }
96 catch
97 {
98 SockeClient.Disconnect(true);
99 Console.WriteLine("客户端 {0} 断开连接", IP);
100 SessionPool.Remove(IP);
101 }
102 }
103 #endregion
104 #region 客户端和服务端的响应
105 /*
106 * 客户端向服务器发送请求
107 *
108 * GET / HTTP/1.1
109 * Origin: http://localhost:1416
110 * Sec-WebSocket-Key: vDyPp55hT1PphRU5OAe2Wg==
111 * Connection: Upgrade
112 * Upgrade: Websocket
113 *Sec-WebSocket-Version: 13
114 * User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
115 * Host: localhost:8064
116 * DNT: 1
117 * Cache-Control: no-cache
118 * Cookie: DTRememberName=admin
119 *
120 * 服务器给出响应
121 *
122 * HTTP/1.1 101 Switching Protocols
123 * Upgrade: websocket
124 * Connection: Upgrade
125 * Sec-WebSocket-Accept: xsOSgr30aKL2GNZKNHKmeT1qYjA=
126 *
127 * 在请求中的“Sec-WebSocket-Key”是随机的,服务器端会用这些数据来构造出一个SHA-1的信息摘要。把“Sec-WebSocket-Key”加上一个魔幻字符串
128 * “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用 SHA-1 加密,之后进行 BASE-64编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端
129 */
130 #endregion
131
132 #region 打包请求连接数据
133 ///
134 /// 打包请求连接数据
135 ///
136 ///
137 ///
138 ///
139 private byte[] PackageHandShakeData(byte[] handShakeBytes, int length)
140 {
141 string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0, length);
142 string key = string.Empty;
143 Regex reg = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n");
144 Match m = reg.Match(handShakeText);
145 if (m.Value != "")
146 {
147 key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$1").Trim();
148 }
149 byte[] secKeyBytes = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
150 string secKey = Convert.ToBase64String(secKeyBytes);
151 var responseBuilder = new StringBuilder();
152 responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + "\r\n");
153 responseBuilder.Append("Upgrade: websocket" + "\r\n");
154 responseBuilder.Append("Connection: Upgrade" + "\r\n");
155 responseBuilder.Append("Sec-WebSocket-Accept: " + secKey + "\r\n\r\n");
156 return Encoding.UTF8.GetBytes(responseBuilder.ToString());
157 }
158 #endregion
159
160 #region 处理接收的数据
161 ///
162 /// 处理接收的数据
163 /// 参考 http://www.cnblogs.com/smark/archive/2012/11/26/2789812.html
164 ///
165 ///
166 ///
167 ///
168 private string AnalyzeClientData(byte[] recBytes, int length)
169 {
170 int start = 0;
171 // 如果有数据则至少包括3位
172 if (length 2) return "";
173 // 判断是否为结束针
174 bool IsEof = (recBytes[start] >> 7) > 0;
175 // 暂不处理超过一帧的数据
176 if (!IsEof) return "";
177 start++;
178 // 是否包含掩码
179 bool hasMask = (recBytes[start] >> 7) > 0;
180 // 不包含掩码的暂不处理
181 if (!hasMask) return "";
182 // 获取数据长度
183 UInt64 mPackageLength = (UInt64)recBytes[start] & 0x7F;
184 start++;
185 // 存储4位掩码值
186 byte[] Masking_key = new byte[4];
187 // 存储数据
188 byte[] mDataPackage;
189 if (mPackageLength == 126)
190 {
191 // 等于126 随后的两个字节16位表示数据长度
192 mPackageLength = (UInt64)(recBytes[start] 8 | recBytes[start + 1]);
193 start += 2;
194 }
195 if (mPackageLength == 127)
196 {
197 // 等于127 随后的八个字节64位表示数据长度
198 mPackageLength = (UInt64)(recBytes[start] 8 * 7) | recBytes[start] 8 * 6) | recBytes[start] 8 * 5) | recBytes[start] 8 * 4) | recBytes[start] 8 * 3) | recBytes[start] 8 * 2) | recBytes[start] 8 | recBytes[start + 1]);
199 start += 8;
200 }
201 mDataPackage = new byte[mPackageLength];
202 for (UInt64 i = 0; i )
203 {
204 mDataPackage[i] = recBytes[i + (UInt64)start + 4];
205 }
206 Buffer.BlockCopy(recBytes, start, Masking_key, 0, 4);
207 for (UInt64 i = 0; i )
208 {
209 mDataPackage[i] = (byte)(mDataPackage[i] ^ Masking_key[i % 4]);
210 }
211 return Encoding.UTF8.GetString(mDataPackage);
212 }
213 #endregion
214
215 #region 发送数据
216 ///
217 /// 把发送给客户端消息打包处理(拼接上谁什么时候发的什么消息)
218 ///
219 /// The data.
220 /// Message.
221 private byte[] PackageServerData(string msg)
222 {
223 byte[] content = null;
224 byte[] temp = Encoding.UTF8.GetBytes(msg);
225 if (temp.Length 126)
226 {
227 content = new byte[temp.Length + 2];
228 content[0] = 0x81;
229 content[1] = (byte)temp.Length;
230 Buffer.BlockCopy(temp, 0, content, 2, temp.Length);
231 }
232 else if (temp.Length 0xFFFF)
233 {
234 content = new byte[temp.Length + 4];
235 content[0] = 0x81;
236 content[1] = 126;
237 content[2] = (byte)(temp.Length & 0xFF);
238 content[3] = (byte)(temp.Length >> 8 & 0xFF);
239 Buffer.BlockCopy(temp, 0, content, 4, temp.Length);
240 }
241 return content;
242 }
243 #endregion
Session
1 public class Session
2 {
3 private Socket _sockeclient;
4 private byte[] _buffer;
5 private string _ip;
6 private bool _isweb = false;
7
8 public Socket SockeClient
9 {
10 set { _sockeclient = value; }
11 get { return _sockeclient; }
12 }
13
14 public byte[] buffer
15 {
16 set { _buffer = value; }
17 get { return _buffer; }
18 }
19
20 public string IP
21 {
22 set { _ip = value; }
23 get { return _ip; }
24 }
25
26 public bool isWeb
27 {
28 set { _isweb = value; }
29 get { return _isweb; }
30 }
31 }
C# socket异步 服务端
标签:stream remote start oba class replace app local temp
原文地址:http://www.cnblogs.com/qc-id-01/p/7520633.html
评论