1 public sealed class SocketOperation
2 {
3 string strBufferLeft = string.Empty;
4
5 public SocketOperation()
6 {
7 }
8
9 /**/
10 /// <summary>
11 /// 连接使用 tcp 协议的服务端
12 /// </summary>
13 /// <param name="ip">服务端的ip地址</param>
14 /// <param name="port">服务端的端口号</param>
15 /// <returns></returns>
16 public Socket ConnectServer(string ip, int port)
17 {
18 Socket s = null;
19
20 try
21 {
22 IPAddress ipAddress = IPAddress.Parse(ip);
23 IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);
24 //EndPoint EndPointLocal=(EndPoint)(new IPEndPoint(IPAddress.Parse(Global.PCIP), 35001));
25
26 s = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
27 //s.Bind(EndPointLocal);
28 if (0 != Global.TestCount)
29 {
30 Thread.Sleep(15000);
31 }
32 //MessageBox.Show(Global.PCIP);
33 s.Connect(ipEndPoint);
34 //MessageBox.Show(s.Connected.ToString());
35 if (s.Connected == false)
36 {
37 s = null;
38 }
39 }
40 catch (Exception e)
41 {
42 //Log.WriteLog ( e );
43 }
44 return s;
45 }
46
47 /**/
48 /// <summary>
49 /// 用主机名称连接使用Tcp协议的服务端
50 /// </summary>
51 /// <param name="hostName">在hosts 文件中存在的主机名称</param>
52 /// <param name="port">服务端的端口号</param>
53 /// <returns></returns>
54 public Socket ConnectServByHostName(string hostName, int port)
55 {
56 Socket s = null;
57 IPHostEntry iphe = null;
58
59 try
60 {
61 iphe = Dns.Resolve(hostName);
62 foreach (IPAddress ipad in iphe.AddressList)
63 {
64 IPEndPoint ipe = new IPEndPoint(ipad, port);
65 Socket tmps = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
66 tmps.Connect(ipe);
67
68 if (tmps.Connected)
69 {
70 s = tmps;
71 break;
72 }
73 else
74 continue;
75 }
76 }
77 catch (Exception e)
78 {
79 //Log.WriteLog ( e );
80 }
81 return s;
82 }
83
84 /**/
85 /// <summary>
86 /// 向远程主机发送数据
87 /// </summary>
88 /// <param name="socket">要发送数据且已经连接到远程主机的 Socket</param>
89 /// <param name="buffer">待发送的数据</param>
90 /// <param name="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>
91 /// <returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>
92 /// <remarks >
93 /// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
94 /// </remarks>
95 public int SendData(Socket socket, byte[] buffer, int outTime)
96 {
97 if (socket == null || socket.Connected == false)
98 {
99 throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
100 }
101 if (buffer == null || buffer.Length == 0)
102 {
103 throw new ArgumentException("参数buffer 为null ,或者长度为 0");
104 }
105
106 int flag = 0;
107 try
108 {
109 int left = buffer.Length;
110 int sndLen = 0;
111
112 while (true)
113 {
114 if ((socket.Poll(outTime * 1000000, SelectMode.SelectWrite) == true))
115 { // 收集了足够多的传出数据后开始发送
116 sndLen = socket.Send(buffer, sndLen, left, SocketFlags.None);
117 left -= sndLen;
118 if (left == 0)
119 { // 数据已经全部发送
120 flag = 0;
121 break;
122 }
123 else
124 {
125 if (sndLen > 0)
126 { // 数据部分已经被发送
127 continue;
128 }
129 else
130 { // 发送数据发生错误
131 flag = -2;
132 break;
133 }
134 }
135 }
136 else
137 { // 超时退出
138 flag = -1;
139 break;
140 }
141 }
142 }
143 catch (SocketException e)
144 {
145 //Log.WriteLog ( e );
146 flag = -3;
147 }
148 return flag;
149 }
150
151
152 /**/
153 /// <summary>
154 /// 向远程主机发送数据
155 /// </summary>
156 /// <param name="socket">要发送数据且已经连接到远程主机的 Socket</param>
157 /// <param name="buffer">待发送的字符串</param>
158 /// <param name="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>
159 /// <returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>
160 /// <remarks >
161 /// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
162 /// </remarks>
163 public int SendData(Socket socket, string buffer, int outTime)
164 {
165 if (buffer == null || buffer.Length == 0)
166 {
167 throw new ArgumentException("待发送的字符串长度不能为零.");
168 }
169 return (SendData(socket, System.Text.Encoding.Default.GetBytes(buffer), outTime));
170 }
171
172
173 /**/
174 /// <summary>
175 /// 接收远程主机发送的数据
176 /// </summary>
177 /// <param name="socket">要接收数据且已经连接到远程主机的 socket</param>
178 /// <param name="buffer">接收数据的缓冲区</param>
179 /// <param name="outTime">接收数据的超时时间,以秒为单位,可以精确到微秒</param>
180 /// <returns>0:接收数据成功;-1:超时;-2:接收数据出现错误;-3:接收数据时出现异常</returns>
181 /// <remarks >
182 /// 1、当 outTime 指定为-1时,将一直等待直到有数据需要接收;
183 /// 2、需要接收的数据的长度,由 buffer 的长度决定。
184 /// </remarks>
185 public int RecvData(Socket socket, byte[] buffer, int outTime)
186 {
187 if (socket == null || socket.Connected == false)
188 {
189 throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
190 }
191 if (buffer == null || buffer.Length == 0)
192 {
193 throw new ArgumentException("参数buffer 为null ,或者长度为 0");
194 }
195 buffer.Initialize();
196 int left = buffer.Length;
197 int curRcv = 0;
198 int flag = 0;
199
200 try
201 {
202 while (true)
203 {
204 if (socket.Poll(outTime * 1000000, SelectMode.SelectRead) == true)
205 { // 已经有数据等待接收
206 curRcv = socket.Receive(buffer, curRcv, left, SocketFlags.None);
207 left -= curRcv;
208 if (left == 0)
209 { // 数据已经全部接收
210 flag = 0;
211 break;
212 }
213 else
214 {
215 if (curRcv > 0)
216 { // 数据已经部分接收
217 continue;
218 }
219 else
220 { // 出现错误
221 flag = -2;
222 break;
223 }
224 }
225 }
226 else
227 { // 超时退出
228 flag = -1;
229 break;
230 }
231 }
232 }
233 catch (SocketException e)
234 {
235 //Log.WriteLog ( e );
236 flag = -3;
237 }
238 return flag;
239 }
240
241 /**/
242 /// <summary>
243 /// 接收远程主机发送的数据
244 /// </summary>
245 /// <param name="socket">要接收数据且已经连接到远程主机的 socket</param>
246 /// <param name="buffer">存储接收到的数据的字符串</param>
247 /// <param name="bufferLen">待接收的数据的长度</param>
248 /// <param name="outTime">接收数据的超时时间,以秒为单位,可以精确到微秒</param>
249 /// <returns>0:接收数据成功;-1:超时;-2:接收数据出现错误;-3:接收数据时出现异常</returns>
250 /// <remarks >
251 /// 当 outTime 指定为-1时,将一直等待直到有数据需要接收;
252 /// </remarks>
253 public int RecvData(Socket socket, string buffer, int bufferLen, int outTime)
254 {
255 if (bufferLen <= 0)
256 {
257 throw new ArgumentException("存储待接收数据的缓冲区长度必须大于0");
258 }
259 byte[] tmp = new byte[bufferLen];
260 int flag = 0;
261 if ((flag = RecvData(socket, tmp, outTime)) == 0)
262 {
263 buffer = System.Text.Encoding.Default.GetString(tmp);
264 }
265 return flag;
266 }
267
268
269 /**/
270 /// <summary>
271 /// 向远程主机发送文件
272 /// </summary>
273 /// <param name="socket" >要发送数据且已经连接到远程主机的 socket</param>
274 /// <param name="fileName">待发送的文件名称</param>
275 /// <param name="maxBufferLength">文件发送时的缓冲区大小</param>
276 /// <param name="outTime">发送缓冲区中的数据的超时时间</param>
277 /// <returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>
278 /// <remarks >
279 /// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
280 /// </remarks>
281 public int SendFile(Socket socket, string fileName, int maxBufferLength, int outTime)
282 {
283 if (fileName == null || maxBufferLength <= 0)
284 {
285 throw new ArgumentException("待发送的文件名称为空或发送缓冲区的大小设置不正确.");
286 }
287
288 int flag = 0;
289 try
290 {
291 FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
292 long fileLen = fs.Length; // 文件长度
293 long leftLen = fileLen; // 未读取部分
294 int readLen = 0; // 已读取部分
295 byte[] buffer = null;
296
297 if (fileLen <= maxBufferLength)
298 { /**//* 文件可以一次读取*/
299 buffer = new byte[fileLen];
300 readLen = fs.Read(buffer, 0, (int)fileLen);
301 flag = SendData(socket, buffer, outTime);
302 }
303 else
304 { /**//* 循环读取文件,并发送 */
305 buffer = new byte[maxBufferLength];
306 while (leftLen != 0)
307 {
308 readLen = fs.Read(buffer, 0, maxBufferLength);
309 if ((flag = SendData(socket, buffer, outTime)) < 0)
310 {
311 break;
312 }
313 leftLen -= readLen;
314 }
315 }
316 fs.Close();
317 }
318 catch (IOException e)
319 {
320 //Log.WriteLog ( e );
321 flag = -4;
322 }
323 return flag;
324 }
325
326 /**/
327 /// <summary>
328 /// 向远程主机发送文件
329 /// </summary>
330 /// <param name="socket" >要发送数据且已经连接到远程主机的 socket</param>
331 /// <param name="fileName">待发送的文件名称</param>
332 /// <returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>
333 public int SendFile(Socket socket, string fileName)
334 {
335 return SendFile(socket, fileName, 2048, 1);
336 }
337
338
339 /**/
340 /// <summary>
341 /// 接收远程主机发送的文件
342 /// </summary>
343 /// <param name="socket">待接收数据且已经连接到远程主机的 socket</param>
344 /// <param name="fileName">保存接收到的数据的文件名</param>
345 /// <param name="fileLength" >待接收的文件的长度</param>
346 /// <param name="maxBufferLength">接收文件时最大的缓冲区大小</param>
347 /// <param name="outTime">接受缓冲区数据的超时时间</param>
348 /// <returns>0:接收文件成功;-1:超时;-2:接收文件出现错误;-3:接收文件出现异常;-4:写入接收文件发生错误</returns>
349 /// <remarks >
350 /// 当 outTime 指定为-1时,将一直等待直到有数据需要接收
351 /// </remarks>
352 public int RecvFile(Socket socket, string fileName, long fileLength, int maxBufferLength, int outTime)
353 {
354 if (fileName == null || maxBufferLength <= 0)
355 {
356 throw new ArgumentException("保存接收数据的文件名称为空或发送缓冲区的大小设置不正确.");
357 }
358
359 int flag = 0;
360 try
361 {
362 FileStream fs = new FileStream(fileName, FileMode.Create);
363 byte[] buffer = null;
364
365 if (fileLength <= maxBufferLength)
366 { /**//* 一次读取所传送的文件 */
367 buffer = new byte[fileLength];
368 if ((flag = RecvData(socket, buffer, outTime)) == 0)
369 {
370 fs.Write(buffer, 0, (int)fileLength);
371 }
372 }
373 else
374 { /**//* 循环读取网络数据,并写入文件 */
375 int rcvLen = maxBufferLength;
376 long leftLen = fileLength; //剩下未写入的数据
377 buffer = new byte[rcvLen];
378
379 while (leftLen != 0)
380 {
381 if ((flag = RecvData(socket, buffer, outTime)) < 0)
382 {
383 break;
384 }
385 fs.Write(buffer, 0, rcvLen);
386 leftLen -= rcvLen;
387 rcvLen = (maxBufferLength < leftLen) ? maxBufferLength : ((int)leftLen);
388 }
389 }
390 fs.Close();
391 }
392 catch (IOException e)
393 {
394 //Log.WriteLog ( e );
395 flag = -4;
396 }
397 return flag;
398 }
399
400 /**/
401 /// <summary>
402 /// 接收远程主机发送的文件
403 /// </summary>
404 /// <param name="socket">待接收数据且已经连接到远程主机的 socket</param>
405 /// <param name="fileName">保存接收到的数据的文件名</param>
406 /// <param name="fileLength" >待接收的文件的长度</param>
407 /// <returns>0:接收文件成功;-1:超时;-2:接收文件出现错误;-3:接收文件出现异常;-4:写入接收文件发生错误</returns>
408 public int RecvFile(Socket socket, string fileName, long fileLength)
409 {
410 return RecvFile(socket, fileName, fileLength, 2048, 1);
411 }
412
413 //public static int SendAndReceive(Socket socket, string strCmd, out string strBuffer, TimeSpan timeout)
414 //{
415 // try
416 // {
417 // return 0;
418 // }
419 // catch (Exception ex)
420 // {
421 // return -1;
422 // }
423 //}
424
425 public bool SendCmd(Socket socket, string strCmd, out string strErrorInfo)
426 {
427 strErrorInfo = string.Empty;
428 byte[] byteCmd;
429 //int flag = 0;
430 int left = 0;
431 int sndLen = 0;
432 int outTime = 60;
433
434 try
435 {
436 if (null == socket || !socket.Connected)
437 {
438 strErrorInfo = "socket is null or unconnected.";
439 return false;
440 }
441
442 if (string.IsNullOrEmpty(strCmd))
443 {
444 strErrorInfo = "Cmd is null or empty.";
445 return false;
446 }
447
448 byteCmd = Encoding.UTF8.GetBytes(strCmd);
449 left = byteCmd.Length;
450 while (true)
451 {
452 if ((socket.Poll(outTime * 1000000, SelectMode.SelectWrite) == true))
453 { // 收集了足够多的传出数据后开始发送
454 sndLen = socket.Send(byteCmd, sndLen, left, SocketFlags.None);
455 left -= sndLen;
456 if (left == 0)
457 { // 数据已经全部发送
458 //flag = 0;
459 break;
460 }
461 else
462 {
463 if (sndLen > 0)
464 { // 数据部分已经被发送
465 continue;
466 }
467 else
468 { // 发送数据发生错误
469 //flag = -2;
470 //break;
471 strErrorInfo = "Send cmd error.";
472 return false;
473 }
474 }
475 }
476 else
477 { // 超时退出
478 //flag = -1;
479 //break;
480 strErrorInfo = "Send cmd timeout.";
481 return false;
482 }
483 }
484
485 Global.frmAUACOSS.Invoke(Global.frmAUACOSS.updateRTxt, Global.frmAUACOSS.rtxtDEBUG, PrintLevel.Zero, "发送报文:\n" + strCmd + "\n\n", Color.Black, true);
486
487 return true;
488
489 }
490 catch (Exception ex)
491 {
492 strErrorInfo = "Send cmd occurs Ex: " + ex.ToString();
493 return false;
494 }
495 }
496
497 public bool WaitReply(Socket socket, string strWaitString, out string strBuffer, TimeSpan timeout, out string strErrorInfo)
498 {
499 strBuffer = string.Empty;
500 string strBufferTemp = string.Empty;
501 strErrorInfo = string.Empty;
502 int bufferLen = 10240;
503 byte[] tmp = new byte[bufferLen];
504 int left = 0;
505 int curRcv = 0;
506 //int flag = 0;
507
508 bool IsContainWaitString = false;
509
510 try
511 {
512 if (null == socket || !socket.Connected)
513 {
514 strErrorInfo = "socket is null or unconnected.";
515 return false;
516 }
517
518 tmp.Initialize();
519 left = tmp.Length;
520 strBuffer = strBufferLeft;
521
522 while (true)
523 {
524 if (socket.Poll((int)timeout.TotalSeconds * 1000000, SelectMode.SelectRead) == true)
525 { // 已经有数据等待接收
526 // curRcv = socket.Receive(tmp, curRcv, left, SocketFlags.None);
527 // left -= curRcv;
528 // if (left == 0)
529 // { // 数据已经全部接收
530 // //flag = 0;
531 // break;
532 // }
533 // else
534 // {
535 // if (curRcv > 0)
536 // { // 数据已经部分接收
537 // continue;
538 // }
539 // else
540 // { // 出现错误
541 // //flag = -2;
542 // strErrorInfo = "Receive buffer error.";
543 // break;
544 // }
545 // }
546
547 curRcv = socket.Receive(tmp, curRcv, left, SocketFlags.None);
548
549 strBufferTemp = Encoding.UTF8.GetString(tmp);
550
551 strBuffer = strBuffer.Trim('\0');
552
553 strBuffer += strBufferTemp;
554
555 foreach (string strWaitStringTemp in strWaitString.Split('|'))
556 {
557 if (strBuffer.Contains(strWaitStringTemp))
558 {
559 IsContainWaitString = true;
560 break;
561 }
562 }
563 if (IsContainWaitString)
564 {
565 strBufferLeft = strBuffer.Substring(strBuffer.IndexOf(strWaitString) + strWaitString.Length);
566 strBuffer = strBuffer.Substring(0, strBuffer.IndexOf(strWaitString) + strWaitString.Length);
567 break;
568 }
569 }
570 else
571 { // 超时退出
572 //flag = -1;
573 strErrorInfo = "Receive buffer timeout.";
574 return false;
575 }
576 }
577
578 Global.frmAUACOSS.Invoke(Global.frmAUACOSS.updateRTxt, Global.frmAUACOSS.rtxtDEBUG, PrintLevel.Zero, "接收报文:\n" + strBuffer + "\n\n", Color.Black, true);
579
580 return true;
581 }
582 catch (Exception ex)
583 {
584 strErrorInfo = "Wait reply occurs Ex: " + ex.ToString();
585 return false;
586 }
587 }
588 }