songjun
2024-09-04 cc908053e0b5075fbfd27350b6da4b39bca9e550
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Data;
using System.Threading;
using System.IO.Compression;
 
namespace BatchService.Framework.Utility
{
    public class SocketProcess
    {
        private bool _isCompression = false;
        private Socket _socket;
        private bool _isRunning = false;
        public event Action<byte[], Socket> Event_ReceiveDataFromSocket;
        /// <summary>
        /// 发送SOCKET至远程服务端口
        /// </summary>
        /// <param name="i_data">数据包</param>
        /// <param name="ipAddress">IP地址(192.168.1.1)</param>
        /// <param name="port">端口</param>
        /// <param name="isCompression">是否启用压缩</param>
        public byte[] Send(byte[] i_data, string ipAddress, int port, bool isCompression)
        {
            //创建终结点EndPoint
            IPAddress ip = IPAddress.Parse(ipAddress);
            IPEndPoint ipe = new IPEndPoint(ip, port);   //把ip和端口转化为IPEndPoint的实例
 
            //LogHelper.Debug(string.Format("准备发送的数据包字节数:{0},IP:{1},Port:{2}", i_data.Length, ipAddress, port));
            //创建Socket并连接到服务器
            Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);   //  创建Socket
            //LogHelper.Debug("Connecting...");
            c.Connect(ipe); //连接到服务器
 
            //向服务器发送信息
            //LogHelper.Debug("Send message");
            if (isCompression)
            {
                c.Send(this.Compress(i_data));
            }
            else
            {
                c.Send(i_data); //发送信息
            }
            //接受从服务器返回的信息
            byte[] recvBytes = new byte[1024];
            int bytes;
            bytes = c.Receive(recvBytes, recvBytes.Length, 0);    //从服务器端接受返回信息
            byte[] recvBytes2 = new byte[bytes];
            Array.Copy(recvBytes, 0, recvBytes2, 0, bytes);
            //一定记着用完Socket后要关闭
            c.Close(); 
            return recvBytes2;
        }
 
        public void Listen(int i_port, bool isCompression)
        {
            _isCompression = isCompression;
            if (_isRunning)
            {
                LogHelper.Debug("监听服务已经在运行...不响应此次开启请求");
                return;
            }
            try
            {
                LogHelper.Debug(string.Format("准备开启监听线程,端口号:{0}...", i_port));
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
                _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);
                _socket.NoDelay = false;
 
                IPEndPoint iep = new IPEndPoint(IPAddress.Any, i_port);
                _socket.Bind(iep);
                _isRunning = true;
                _socket.Listen(100);
                LogHelper.Debug(string.Format("端口号为:{0}的监听线程开启完成", i_port));
 
                ThreadPool.QueueUserWorkItem(new WaitCallback(Accept));
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
        }
        protected virtual void Accept(object iar)
        {
            while (_isRunning)
            {
                try
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(AcceptConn), _socket.Accept());
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex.ToString());
                }
            }
        }
        protected virtual void AcceptConn(object iar)
        {
            Socket client = iar as Socket;
            try
            {
                if (client == null)
                {
                    return;
                }
                LogHelper.Debug(string.Format("收到{0}发来的数据请求", client.RemoteEndPoint.ToString()));
 
                int rec = 0;
                //缓存区2M
                byte[] tempData = new byte[1024 * 10];
                int bytecount = 0;
                while (1 == 1)
                {
                    try
                    {
                        bytecount = client.Receive(tempData, rec, tempData.Length - rec, SocketFlags.None);
                        rec += bytecount;
                        //接收到客户端关闭的消息 
                        if (bytecount == 0)
                        {
                            client.Close();
                            LogHelper.Debug("未收到任何数据");
                        }
                        Array.Resize(ref tempData, rec);
                        if (_isCompression)
                        {
                            tempData = this.Decompress(tempData, tempData.Length);
                        }
                        LogHelper.Debug(string.Format("收到{0}字节", rec));
                        if (Event_ReceiveDataFromSocket != null)
                        {
                            Event_ReceiveDataFromSocket(tempData, client);
                        }
                        LogHelper.Debug("接收完成!");
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(string.Format("发生了错误:{0}", ex.ToString()));
                    }
                    finally
                    {
                        client.Shutdown(SocketShutdown.Both);
                    }
                    Thread.Sleep(500);
                    break;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(string.Format("来自的连接发生了错误:{0}", ex.ToString()));
            }
        }
 
        private byte[] Compress(byte[] i_byte_array)
        {
            byte[] t_bytes;
            MemoryStream t_MemoryStream = new MemoryStream();
            GZipStream t_GZipStream = new GZipStream(t_MemoryStream, CompressionMode.Compress, true);
            t_GZipStream.Write(i_byte_array, 0, i_byte_array.Length);
            t_GZipStream.Close();
            t_GZipStream.Dispose();
            //必须把stream流关闭才能返回ms流数据,不然数据会不完整
            //并且解压缩方法stream.Read(buffer, 0, buffer.Length)时会返回0
            t_bytes = t_MemoryStream.ToArray();
            t_MemoryStream.Close();
            t_MemoryStream.Dispose();
            return t_bytes;
        }
 
        /// <summary>
        /// 解压数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private byte[] Decompress(byte[] i_byte_array, int i_byte_length)
        {
            byte[] t_bytes;
            MemoryStream t_MemoryStream = new MemoryStream();
            t_MemoryStream.Write(i_byte_array, 0, i_byte_array.Length);
            t_MemoryStream.Position = 0;
            GZipStream t_GZipStream = new GZipStream(t_MemoryStream, CompressionMode.Decompress, true);
            byte[] t_buffer = new byte[i_byte_length];
            MemoryStream t_temp_MemoryStream = new MemoryStream();
            int t_read = t_GZipStream.Read(t_buffer, 0, t_buffer.Length);
            while (t_read > 0)
            {
                t_temp_MemoryStream.Write(t_buffer, 0, t_read);
                t_read = t_GZipStream.Read(t_buffer, 0, t_buffer.Length);
            }
            //必须把stream流关闭才能返回ms流数据,不然数据会不完整
            t_GZipStream.Close();
            t_GZipStream.Dispose();
            t_MemoryStream.Close();
            t_MemoryStream.Dispose();
            t_bytes = t_temp_MemoryStream.ToArray();
            t_temp_MemoryStream.Close();
            t_temp_MemoryStream.Dispose();
            return t_bytes;
        }
    }
}