最近在开发TCPIP通信,封装了3个类,望各位大神指点指点。
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. using System.Net;
  7. using System.Linq;
  8. using System.Net.NetworkInformation;
  9.  
  10. namespace HY_RFID
  11. {
  12. public class MyTCPServer
  13. {
  14. public bool isExit = false;
  15. private TcpListener listener;
  16. public TcpClient readClient;
  17. List<ReadWriteObject> rws = new List<ReadWriteObject>();
  18. public List<TCPIP> ips = new List<TCPIP>();
  19.  
  20. #region 创建事件
  21. //声明事件参数
  22. public class TcpClientArgs : EventArgs
  23. {
  24. public readonly TcpClient client;
  25. public TcpClientArgs(TcpClient client)
  26. {
  27. this.client = client;
  28. }
  29. }
  30. public class BackMsgArgs : EventArgs
  31. {
  32. public readonly string backMsg;
  33. public BackMsgArgs(string backMsg)
  34. {
  35. this.backMsg = backMsg;
  36. }
  37. }
  38. public class BackByteArgs : EventArgs
  39. {
  40. public readonly byte[] backByte;
  41. public BackByteArgs(byte[] backByte)
  42. {
  43. this.backByte = backByte;
  44. }
  45. }
  46. public delegate void WaitConnectEventHandler(object sender,EventArgs e);
  47. public event WaitConnectEventHandler OnWaitConnect;
  48. protected virtual void WaitConnect()
  49. {
  50. if (OnWaitConnect != null)// 如果有对象注册
  51. {
  52. OnWaitConnect(this, null);// 调用所有注册对象的方法
  53. }
  54. }
  55. //声明委托
  56. public delegate void SuccessConnectEventHandler(object sender, TcpClientArgs e);
  57. //声明事件
  58. public event SuccessConnectEventHandler OnSuccessConnect;
  59. //触发方法
  60. protected virtual void SuccessConnect(TcpClientArgs e)
  61. {
  62. if (OnSuccessConnect != null)// 如果有对象注册
  63. {
  64. OnSuccessConnect(this, e);// 调用所有注册对象的方法
  65. }
  66. }
  67. public delegate void ReadCallBackMsgEventHandler(object sender, BackByteArgs e);
  68. public event ReadCallBackMsgEventHandler OnReadCallBack;
  69. protected virtual void ReadCallBackMsg(BackByteArgs e)
  70. {
  71. if (OnReadCallBack != null)// 如果有对象注册
  72. {
  73. OnReadCallBack(this, e);// 调用所有注册对象的方法
  74. }
  75. }
  76. public delegate void ReadErrorCallBackMsgEventHandler(object sender, BackMsgArgs e);
  77. public event ReadErrorCallBackMsgEventHandler OnReadErrorCallBack;
  78. protected virtual void ReadErrorCallBackMsg(BackMsgArgs e)
  79. {
  80. if (OnReadErrorCallBack != null)// 如果有对象注册
  81. {
  82. OnReadErrorCallBack(this, e);// 调用所有注册对象的方法
  83. }
  84. }
  85. #endregion
  86.  
  87. //用于线程同步,初始状态设为非终止状态,使用手动重置方式
  88. private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);
  89. //服务端监听方法
  90. public void ServerListen(int port)
  91. {
  92. //由于服务器要为多个客户服务,所以需要创建一个线程监听客户端连接请求
  93. isExit = false;
  94. if (!PortInUse(port))
  95. {
  96. Thread myThread = new Thread(new ParameterizedThreadStart(AcceptConnect));
  97. myThread.Start(port);
  98. }
  99. else
  100. {
  101. throw new Exception("当前端口已被占用!");
  102. }
  103. }
  104. /// <summary>
  105. /// 检测但钱端口是否被占用
  106. /// </summary>
  107. /// <param name="port"></param>
  108. /// <returns></returns>
  109. private bool PortInUse(int port)
  110. {
  111. bool inUse = false;
  112. //获取所有的监听连接
  113. IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
  114. IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
  115. foreach (IPEndPoint endPoint in ipEndPoints)
  116. {
  117. if (endPoint.Port == port)
  118. {
  119. inUse = true;
  120. break;
  121. }
  122. }
  123. return inUse;
  124. }
  125. //与客户机取得连接
  126. private void AcceptConnect(object o)
  127. {
  128. try
  129. {
  130. if (o == null) return;
  131. IPAddress ip4 = GetLocalIpv4() as IPAddress;
  132. listener = new TcpListener(ip4, Convert.ToInt32(o));
  133. listener.Start();
  134. //引用在异步操作完成时调用的回调方法
  135. AsyncCallback callback = new AsyncCallback(AcceptTcpClientCallback);
  136. while (!isExit)
  137. {
  138.  
  139. //将事件的状态设为非终止
  140. allDone.Reset();
  141. //触发等待事件
  142. WaitConnect();
  143. //开始一个异步操作接受传入的连接尝试
  144. listener.BeginAcceptTcpClient(callback, listener);
  145. //阻塞当前线程,直到收到客户连接信号
  146. allDone.WaitOne();
  147. Thread.Sleep();
  148. }
  149. }
  150. catch (Exception ex)
  151. {
  152. throw ex;
  153. }
  154. }
  155. //获取本机IP
  156. public object GetLocalIpv4()
  157. {
  158. //获取本机所有IP地址
  159. try
  160. {
  161. IPAddress[] localips = Dns.GetHostAddresses(Dns.GetHostName());
  162. foreach (IPAddress ip in localips)
  163. {
  164. //找到本地所有IP地址符合IPV4协议的IP地址
  165. if (ip.AddressFamily == AddressFamily.InterNetwork)
  166. {
  167. return ip;
  168. }
  169. }
  170. }
  171. catch (Exception ex)
  172. {
  173. throw ex;
  174. }
  175. return null;
  176. }
  177. // 连接客户端的回调函数
  178. //ar是IAsyncResult类型的接口,表示异步操作的状态是由listener.BeginAcceptTcpClient(callback, listener)传递过来的
  179. private void AcceptTcpClientCallback(IAsyncResult ar)
  180. {
  181. lock (this)
  182. {
  183. try
  184. {
  185. if (isExit) return;
  186. //将事件状态设为终止状态,允许一个或多个等待线程继续
  187. allDone.Set();
  188. TcpListener myListener = (TcpListener)ar.AsyncState;
  189. //异步接收传入的连接,并创建新的TcpClient对象处理远程主机通信
  190. TcpClient client = myListener.EndAcceptTcpClient(ar);
  191. //已接受客户连接
  192. TcpClientArgs e = new TcpClientArgs(client);
  193. ReadWriteObject readWriteObject = new ReadWriteObject(client);
  194. rws.Add(readWriteObject);
  195. string[] strs=client.Client.RemoteEndPoint.ToString().Split(':');
  196. ips.RemoveAll(c => c.TargetIP == strs[]);
  197. ips.Add(new TCPIP(strs[], strs[], DateTime.Now));
  198. //触发客户端连接成功事件
  199. SuccessConnect(e);
  200. readWriteObject.netStream.BeginRead(readWriteObject.readBytes, , readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
  201. }
  202. catch (Exception ex)
  203. {
  204. throw ex;
  205. }
  206. }
  207. }
  208. private void ReadCallback(IAsyncResult ar)
  209. {
  210. try
  211. {
  212. ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
  213. readClient=readWriteObject.client;
  214. if (readClient.Client.Poll(, SelectMode.SelectRead) && (readClient.Client.Available == ) | readClient.Client.Connected)
  215. {
  216. throw new Exception(readWriteObject.client.Client.RemoteEndPoint + "【断开】");
  217. }
  218. int length = readWriteObject.netStream.EndRead(ar);
  219. if (length == ) return;
  220. List<byte> _byteData = new List<byte>();
  221. for (int i = ; i < length; i++)
  222. {
  223. _byteData.Add(readWriteObject.readBytes[i]);
  224. }
  225. ReadCallBackMsg(new BackByteArgs(_byteData.ToArray()));
  226. if (isExit == false)
  227. {
  228. readWriteObject.InitReadArray();
  229. readWriteObject.netStream.BeginRead(readWriteObject.readBytes, , readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
  230. }
  231. }
  232. catch (Exception ex)
  233. {
  234. ReadErrorCallBackMsg(new BackMsgArgs(ex.Message));
  235. }
  236. }
  237. public void SendString(string remoteEndPoint, string str)
  238. {
  239. try
  240. {
  241. ReadWriteObject readWriteObject = rws.Where(c => c.client.Client.RemoteEndPoint.ToString() == remoteEndPoint).FirstOrDefault();
  242. if (readWriteObject.client.Client.Poll(, SelectMode.SelectRead) && (readWriteObject.client.Client.Available == ) || !readWriteObject.client.Client.Connected)
  243. {
  244. throw new Exception(remoteEndPoint + "【断开】");
  245. }
  246. if (readWriteObject != null)
  247. {
  248. readWriteObject.write = MyHelper.HexToByte(str);
  249. readWriteObject.netStream.BeginWrite(readWriteObject.write, , readWriteObject.write.Length, new AsyncCallback(SendCallBack), readWriteObject);
  250. readWriteObject.netStream.Flush();
  251.  
  252. }
  253. }
  254. catch (Exception ex)
  255. {
  256. throw ex;
  257. }
  258. }
  259. private void SendCallBack(IAsyncResult ar)
  260. {
  261. ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
  262. try
  263. {
  264. readWriteObject.netStream.EndWrite(ar);
  265. }
  266. catch (Exception ex)
  267. {
  268. throw ex;
  269. }
  270. }
  271. /// <summary>
  272. /// 停止服务
  273. /// </summary>
  274. public void StopServer()
  275. {
  276. isExit = true;
  277. allDone.Set();
  278. if (listener != null)
  279. listener.Stop();
  280. }
  281. }
  282. }

TCPServer类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net.Sockets;
  6. using System.Net;
  7. using System.Threading;
  8.  
  9. namespace HY_RFID
  10. {
  11. public class MyTcpClient
  12. {
  13. #region 创建事件
  14. public class RecMsgArgs : EventArgs
  15. {
  16. public readonly string recMsg;
  17. public RecMsgArgs(string recMsg)
  18. {
  19. this.recMsg = recMsg;
  20. }
  21. }
  22. public class RecErrArgs : EventArgs
  23. {
  24. public readonly string recErr;
  25. public RecErrArgs(string recErr)
  26. {
  27. this.recErr = recErr;
  28. }
  29. }
  30. public delegate void ReceivedMsgEventHandler(object sender, RecMsgArgs e);
  31. public event ReceivedMsgEventHandler OnReceived;
  32. protected virtual void ReceivedMsg(RecMsgArgs e)
  33. {
  34. if (OnReceived != null)// 如果有对象注册
  35. {
  36. OnReceived(this, e);// 调用所有注册对象的方法
  37. }
  38. }
  39. public delegate void ReceivedErrorEventHandler(object sender, RecErrArgs e);
  40. public event ReceivedErrorEventHandler OnReceivedErr;
  41. protected virtual void ReceivedError(RecErrArgs e)
  42. {
  43. if (OnReceivedErr != null)// 如果有对象注册
  44. {
  45. OnReceivedErr(this, e);// 调用所有注册对象的方法
  46. }
  47. }
  48. #endregion
  49. private bool isExit;
  50. private Socket socketClient = null;
  51. //连接服务端方法
  52. public void ClientConnect(string IP, string Port)
  53. {
  54. isExit = false;
  55. //定义一个套字节监听 包含3个参数(IP4寻址协议,流式连接,TCP协议)
  56. socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  57. //需要获取文本框中的IP地址
  58. IPAddress ipaddress = IPAddress.Parse(IP);
  59. //将获取的ip地址和端口号绑定到网络节点endpoint上
  60. IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(Port));
  61. //这里客户端套接字连接到网络节点(服务端)用的方法是Connect 而不是Bind
  62. socketClient.Connect(endpoint);
  63. //创建一个线程 用于监听服务端发来的消息
  64. Thread threadClient = new Thread(RecMsg);
  65. //将窗体线程设置为与后台同步
  66. threadClient.IsBackground = true;
  67. //启动线程
  68. threadClient.Start();
  69. }
  70. // 发送节目全屏byte串信息到服务端的方法
  71. public void ClientSendMsg(string msg)
  72. {
  73. try
  74. {
  75. if (socketClient.Poll(, SelectMode.SelectRead) && (socketClient.Available == ) || !socketClient.Connected)
  76. {
  77. throw new Exception(socketClient.RemoteEndPoint + "已断开!");
  78. }
  79. Byte[] data = System.Text.Encoding.Default.GetBytes(msg);
  80. socketClient.Send(data, data.Length, SocketFlags.None);//发送信息
  81. }
  82. catch(Exception ex)
  83. {
  84. throw ex;
  85. }
  86. }
  87. //接收服务端发来信息的方法
  88. public void RecMsg()
  89. {
  90.  
  91. while (!isExit) //持续监听服务端发来的消息
  92. {
  93. try
  94. {
  95. bool o = socketClient.Poll(, SelectMode.SelectRead);
  96. if (o) break;
  97. //定义一个1024*200的内存缓冲区 用于临时性存储接收到的信息
  98. byte[] arrRecMsg = new byte[ * ];
  99. //将客户端套接字接收到的数据存入内存缓冲区, 并获取其长度
  100. int length = socketClient.Receive(arrRecMsg);
  101. if (length == ) return;
  102. string recMsg = Encoding.Default.GetString(arrRecMsg, , length);
  103. ReceivedMsg(new RecMsgArgs(recMsg));
  104. }
  105. catch (SocketException ex)
  106. {
  107. ReceivedError(new RecErrArgs(ex.Message));
  108. }
  109. }
  110. }
  111. /// <summary>
  112. /// 断开链接
  113. /// </summary>
  114. public void StopConnect()
  115. {
  116. if (socketClient != null)
  117. {
  118. socketClient.Close();
  119. isExit = true;
  120. }
  121. }
  122. }
  123. }

TCPClient类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net.Sockets;
  5.  
  6. namespace HY_RFID
  7. {
  8. public class ReadWriteObject
  9. {
  10. public TcpClient client;
  11. public NetworkStream netStream;
  12. public byte[] readBytes;
  13. public byte[] write;
  14. public ReadWriteObject(TcpClient client)
  15. {
  16. this.client = client;
  17. netStream = client.GetStream();
  18. readBytes = new byte[client.ReceiveBufferSize];
  19. write=new byte[client.SendBufferSize];
  20. }
  21. public void InitReadArray()
  22. {
  23. readBytes = new byte[client.ReceiveBufferSize];
  24. }
  25. public void InitWriteArray()
  26. {
  27. write=new byte[client.SendBufferSize];
  28. }
  29. }
  30. }

ReadWriteObject类

TCPIP通信的更多相关文章

  1. 嵌入式Linux软件工程师面试题一

    题一,同步和异步有啥区别? 题二,TCP与UDP有啥区别? 题三,进程和线程有啥区别? 题一答案: 同步(Sync):所有的操作都做完,才返回给用户.这样用户在线等待的时间太长,给用户一种卡死了的感觉 ...

  2. DB2 9.5 数据库分区管理及应用实践

    DB2 数据库分区是 DB2 企业版 DPF(Data Partitioning Feature)选件提供的,它主要用来为大规模数据处理.高并发数据访问提供支持.DB2 数据库分区采用 Share-n ...

  3. 图解TCP-IP协议

    本文通过图来梳理TCP-IP协议相关知识.TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道.如图1所示,给出了TCP通信过程的示意图. 图1 TCP 三次握手四次挥手 图1 ...

  4. TCPIP、Http、Socket的协议~ 写得挺形象,赞

    这篇文章写得挺形象,对TCPIP.HTTP.Socket的作用有一个整体层次的理解. 转载文章内容如下: 网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.   通过初步的了 ...

  5. [TCPIP] 传输控制协议 Note

    TCPIP  TCP 传输控制协议 TCP提供一种面向连接的,可靠的字节流服务. 面向连接意味着两个使用TCP的应用在传输数据之前先建立一个TCP连接,这个过程跟打电话相似.在一个TCP连接中仅有两方 ...

  6. Ⅰ.net通信指前提

    ①大概搜索了一下,一般提到了这三种居多: Webservice:基于B/S的,可以对外发布方法 Socket:一种网络数据交换模型,Socket接口是TCP/IP网络的API,有三个主要因素:地址.端 ...

  7. 拿搬东西来解释udp tcpip bio nio aio aio异步

     [群主]雷欧纳德简单理解 tcpip是有通信确认的面对面通信   有打招呼的过程  有建立通道的过程 有保持通道的确认    有具体传输udp是看到对面的人好像在对面等你 就往对面扔东西[群主]雷欧 ...

  8. Linux之TCPIP内核参数优化

    /proc/sys/net目录 所有的TCP/IP参数都位于/proc/sys/net目录下(请注意,对/proc/sys/net目录下内容的修改都是临时的,任何修改在系统重启后都会丢失),例如下面这 ...

  9. (读书笔记)第2章 TCP-IP的工作方式

    第2章 TCP-IP的工作方式 TCP/IP协议系统 为了实现TCP的功能,TCP/IP的创建者使用了模块化的设计.TCP/IP协议系统被分为不同的组件,每个组件分别负责通信过程的一个步骤.这种模块化 ...

随机推荐

  1. jQuery 的属性操作方法

    jQuery 属性操作方法 下面列出的这些方法获得或设置元素的 DOM 属性. 这些方法对于 XML 文档和 HTML 文档均是适用的,除了:html(). 方法 描述 addClass() 向匹配的 ...

  2. Code Forces Gym 100971D Laying Cables(单调栈)

    D - Laying Cables Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u ...

  3. iptables的实战整理

    一.iptables使用场景:             内网情况下使用:在大并发的情况下不要开iptables否则影响性能 二.iptables出现下面的问题:             在yewufa ...

  4. IO(Input Output)流__字节流

    续: ------->>>>字节流 IntputStream  OutputStream 需求:想要操作图片数据,就需要用到字节流. 读写操作: FileOutputStrea ...

  5. PHP文件操作常用函数总结

    一 .解析路径: 1 获得文件名: basename(); 给出一个包含有指向一个文件的全路径的字符串,本函数返回基本的文件名.如果文件名是以 suffix 结束的,那这一部分也会被去掉. eg: $ ...

  6. 验证码 jsp生成

    <%@ page contentType="image/jpeg" import="java.awt.*, java.awt.image.*,java.util.* ...

  7. java方法的重载

    java方法的重载 public class Person1 {    private String name; //姓名    private int age;      //年龄    priva ...

  8. Lamda和Linq语法对比详细

    本人转载:http://www.cnblogs.com/knowledgesea/p/3897665.html 闲言碎语 近期比较忙,但还是想写点什么,就分享一些基础的知识给大家看吧,希望能帮助一些l ...

  9. 读书雷达 l 业务分析师(BA)篇

    http://chuansong.me/n/412991951441 ThoughtWorks BA社区从2011年起就建立了BA书橱,根据大家的推荐选择了来自软件需求.商业分析.设计思维.软技能,以 ...

  10. Activiti5.16.4数据库表结构

    一.ACTIVITI 数据库E-R图(5.16.4) Activiti 5.16.4 总共有24张表,增加act_evt_log(事件日志),以及增加了对SasS的支持. 在流程定义.运行实例和历史的 ...