最近在开发TCPIP通信,封装了3个类,望各位大神指点指点。
 using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Linq;
using System.Net.NetworkInformation; namespace HY_RFID
{
public class MyTCPServer
{
public bool isExit = false;
private TcpListener listener;
public TcpClient readClient;
List<ReadWriteObject> rws = new List<ReadWriteObject>();
public List<TCPIP> ips = new List<TCPIP>(); #region 创建事件
//声明事件参数
public class TcpClientArgs : EventArgs
{
public readonly TcpClient client;
public TcpClientArgs(TcpClient client)
{
this.client = client;
}
}
public class BackMsgArgs : EventArgs
{
public readonly string backMsg;
public BackMsgArgs(string backMsg)
{
this.backMsg = backMsg;
}
}
public class BackByteArgs : EventArgs
{
public readonly byte[] backByte;
public BackByteArgs(byte[] backByte)
{
this.backByte = backByte;
}
}
public delegate void WaitConnectEventHandler(object sender,EventArgs e);
public event WaitConnectEventHandler OnWaitConnect;
protected virtual void WaitConnect()
{
if (OnWaitConnect != null)// 如果有对象注册
{
OnWaitConnect(this, null);// 调用所有注册对象的方法
}
}
//声明委托
public delegate void SuccessConnectEventHandler(object sender, TcpClientArgs e);
//声明事件
public event SuccessConnectEventHandler OnSuccessConnect;
//触发方法
protected virtual void SuccessConnect(TcpClientArgs e)
{
if (OnSuccessConnect != null)// 如果有对象注册
{
OnSuccessConnect(this, e);// 调用所有注册对象的方法
}
}
public delegate void ReadCallBackMsgEventHandler(object sender, BackByteArgs e);
public event ReadCallBackMsgEventHandler OnReadCallBack;
protected virtual void ReadCallBackMsg(BackByteArgs e)
{
if (OnReadCallBack != null)// 如果有对象注册
{
OnReadCallBack(this, e);// 调用所有注册对象的方法
}
}
public delegate void ReadErrorCallBackMsgEventHandler(object sender, BackMsgArgs e);
public event ReadErrorCallBackMsgEventHandler OnReadErrorCallBack;
protected virtual void ReadErrorCallBackMsg(BackMsgArgs e)
{
if (OnReadErrorCallBack != null)// 如果有对象注册
{
OnReadErrorCallBack(this, e);// 调用所有注册对象的方法
}
}
#endregion //用于线程同步,初始状态设为非终止状态,使用手动重置方式
private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);
//服务端监听方法
public void ServerListen(int port)
{
//由于服务器要为多个客户服务,所以需要创建一个线程监听客户端连接请求
isExit = false;
if (!PortInUse(port))
{
Thread myThread = new Thread(new ParameterizedThreadStart(AcceptConnect));
myThread.Start(port);
}
else
{
throw new Exception("当前端口已被占用!");
}
}
/// <summary>
/// 检测但钱端口是否被占用
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
private bool PortInUse(int port)
{
bool inUse = false;
//获取所有的监听连接
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
foreach (IPEndPoint endPoint in ipEndPoints)
{
if (endPoint.Port == port)
{
inUse = true;
break;
}
}
return inUse;
}
//与客户机取得连接
private void AcceptConnect(object o)
{
try
{
if (o == null) return;
IPAddress ip4 = GetLocalIpv4() as IPAddress;
listener = new TcpListener(ip4, Convert.ToInt32(o));
listener.Start();
//引用在异步操作完成时调用的回调方法
AsyncCallback callback = new AsyncCallback(AcceptTcpClientCallback);
while (!isExit)
{ //将事件的状态设为非终止
allDone.Reset();
//触发等待事件
WaitConnect();
//开始一个异步操作接受传入的连接尝试
listener.BeginAcceptTcpClient(callback, listener);
//阻塞当前线程,直到收到客户连接信号
allDone.WaitOne();
Thread.Sleep();
}
}
catch (Exception ex)
{
throw ex;
}
}
//获取本机IP
public object GetLocalIpv4()
{
//获取本机所有IP地址
try
{
IPAddress[] localips = Dns.GetHostAddresses(Dns.GetHostName());
foreach (IPAddress ip in localips)
{
//找到本地所有IP地址符合IPV4协议的IP地址
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip;
}
}
}
catch (Exception ex)
{
throw ex;
}
return null;
}
// 连接客户端的回调函数
//ar是IAsyncResult类型的接口,表示异步操作的状态是由listener.BeginAcceptTcpClient(callback, listener)传递过来的
private void AcceptTcpClientCallback(IAsyncResult ar)
{
lock (this)
{
try
{
if (isExit) return;
//将事件状态设为终止状态,允许一个或多个等待线程继续
allDone.Set();
TcpListener myListener = (TcpListener)ar.AsyncState;
//异步接收传入的连接,并创建新的TcpClient对象处理远程主机通信
TcpClient client = myListener.EndAcceptTcpClient(ar);
//已接受客户连接
TcpClientArgs e = new TcpClientArgs(client);
ReadWriteObject readWriteObject = new ReadWriteObject(client);
rws.Add(readWriteObject);
string[] strs=client.Client.RemoteEndPoint.ToString().Split(':');
ips.RemoveAll(c => c.TargetIP == strs[]);
ips.Add(new TCPIP(strs[], strs[], DateTime.Now));
//触发客户端连接成功事件
SuccessConnect(e);
readWriteObject.netStream.BeginRead(readWriteObject.readBytes, , readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
}
catch (Exception ex)
{
throw ex;
}
}
}
private void ReadCallback(IAsyncResult ar)
{
try
{
ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
readClient=readWriteObject.client;
if (readClient.Client.Poll(, SelectMode.SelectRead) && (readClient.Client.Available == ) | readClient.Client.Connected)
{
throw new Exception(readWriteObject.client.Client.RemoteEndPoint + "【断开】");
}
int length = readWriteObject.netStream.EndRead(ar);
if (length == ) return;
List<byte> _byteData = new List<byte>();
for (int i = ; i < length; i++)
{
_byteData.Add(readWriteObject.readBytes[i]);
}
ReadCallBackMsg(new BackByteArgs(_byteData.ToArray()));
if (isExit == false)
{
readWriteObject.InitReadArray();
readWriteObject.netStream.BeginRead(readWriteObject.readBytes, , readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
}
}
catch (Exception ex)
{
ReadErrorCallBackMsg(new BackMsgArgs(ex.Message));
}
}
public void SendString(string remoteEndPoint, string str)
{
try
{
ReadWriteObject readWriteObject = rws.Where(c => c.client.Client.RemoteEndPoint.ToString() == remoteEndPoint).FirstOrDefault();
if (readWriteObject.client.Client.Poll(, SelectMode.SelectRead) && (readWriteObject.client.Client.Available == ) || !readWriteObject.client.Client.Connected)
{
throw new Exception(remoteEndPoint + "【断开】");
}
if (readWriteObject != null)
{
readWriteObject.write = MyHelper.HexToByte(str);
readWriteObject.netStream.BeginWrite(readWriteObject.write, , readWriteObject.write.Length, new AsyncCallback(SendCallBack), readWriteObject);
readWriteObject.netStream.Flush(); }
}
catch (Exception ex)
{
throw ex;
}
}
private void SendCallBack(IAsyncResult ar)
{
ReadWriteObject readWriteObject = (ReadWriteObject)ar.AsyncState;
try
{
readWriteObject.netStream.EndWrite(ar);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 停止服务
/// </summary>
public void StopServer()
{
isExit = true;
allDone.Set();
if (listener != null)
listener.Stop();
}
}
}

TCPServer类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading; namespace HY_RFID
{
public class MyTcpClient
{
#region 创建事件
public class RecMsgArgs : EventArgs
{
public readonly string recMsg;
public RecMsgArgs(string recMsg)
{
this.recMsg = recMsg;
}
}
public class RecErrArgs : EventArgs
{
public readonly string recErr;
public RecErrArgs(string recErr)
{
this.recErr = recErr;
}
}
public delegate void ReceivedMsgEventHandler(object sender, RecMsgArgs e);
public event ReceivedMsgEventHandler OnReceived;
protected virtual void ReceivedMsg(RecMsgArgs e)
{
if (OnReceived != null)// 如果有对象注册
{
OnReceived(this, e);// 调用所有注册对象的方法
}
}
public delegate void ReceivedErrorEventHandler(object sender, RecErrArgs e);
public event ReceivedErrorEventHandler OnReceivedErr;
protected virtual void ReceivedError(RecErrArgs e)
{
if (OnReceivedErr != null)// 如果有对象注册
{
OnReceivedErr(this, e);// 调用所有注册对象的方法
}
}
#endregion
private bool isExit;
private Socket socketClient = null;
//连接服务端方法
public void ClientConnect(string IP, string Port)
{
isExit = false;
//定义一个套字节监听 包含3个参数(IP4寻址协议,流式连接,TCP协议)
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//需要获取文本框中的IP地址
IPAddress ipaddress = IPAddress.Parse(IP);
//将获取的ip地址和端口号绑定到网络节点endpoint上
IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(Port));
//这里客户端套接字连接到网络节点(服务端)用的方法是Connect 而不是Bind
socketClient.Connect(endpoint);
//创建一个线程 用于监听服务端发来的消息
Thread threadClient = new Thread(RecMsg);
//将窗体线程设置为与后台同步
threadClient.IsBackground = true;
//启动线程
threadClient.Start();
}
// 发送节目全屏byte串信息到服务端的方法
public void ClientSendMsg(string msg)
{
try
{
if (socketClient.Poll(, SelectMode.SelectRead) && (socketClient.Available == ) || !socketClient.Connected)
{
throw new Exception(socketClient.RemoteEndPoint + "已断开!");
}
Byte[] data = System.Text.Encoding.Default.GetBytes(msg);
socketClient.Send(data, data.Length, SocketFlags.None);//发送信息
}
catch(Exception ex)
{
throw ex;
}
}
//接收服务端发来信息的方法
public void RecMsg()
{ while (!isExit) //持续监听服务端发来的消息
{
try
{
bool o = socketClient.Poll(, SelectMode.SelectRead);
if (o) break;
//定义一个1024*200的内存缓冲区 用于临时性存储接收到的信息
byte[] arrRecMsg = new byte[ * ];
//将客户端套接字接收到的数据存入内存缓冲区, 并获取其长度
int length = socketClient.Receive(arrRecMsg);
if (length == ) return;
string recMsg = Encoding.Default.GetString(arrRecMsg, , length);
ReceivedMsg(new RecMsgArgs(recMsg));
}
catch (SocketException ex)
{
ReceivedError(new RecErrArgs(ex.Message));
}
}
}
/// <summary>
/// 断开链接
/// </summary>
public void StopConnect()
{
if (socketClient != null)
{
socketClient.Close();
isExit = true;
}
}
}
}

TCPClient类

 using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets; namespace HY_RFID
{
public class ReadWriteObject
{
public TcpClient client;
public NetworkStream netStream;
public byte[] readBytes;
public byte[] write;
public ReadWriteObject(TcpClient client)
{
this.client = client;
netStream = client.GetStream();
readBytes = new byte[client.ReceiveBufferSize];
write=new byte[client.SendBufferSize];
}
public void InitReadArray()
{
readBytes = new byte[client.ReceiveBufferSize];
}
public void InitWriteArray()
{
write=new byte[client.SendBufferSize];
}
}
}

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. SOA技术的进化史

    SOA 是一种程序设计思想,其实早在远古时代(计算机史)它就已经出现了.无非就是把系统分解,将数据和业务逻辑部分尽量独立出来,然后以服务形式提供给另外的系统共用. 那时也有一些可以实现 SOA 的工具 ...

  2. Maven source jar get

    Maven作为项目管理的包,同时也能方便的将source-jar下载的本地,省去了每次到网上分别下载的问题. Maven下载Jar包同时下载源文件和文档 示例,在maven生成的工程里面:mvn ec ...

  3. Android studio开发常用快捷键

    最常用快捷键 1.Ctrl+E  可以显示最近编辑的文件列表 2.Shift+Click(点击)  可以关闭文件 3.Ctrl+[或者ctrl+]  可以跳到大括号的开头结尾 4.Ctrl+Shift ...

  4. SampleManager(赛默飞)

  5. 20169210《Linux内核原理与分析》第十周作业

    第一部分:实验 进程的调度时机与进程的切换 操作系统原理中介绍了大量进程调度算法,这些算法从实现的角度看仅仅是从运行队列中选择一个新进程,选择的过程中运用了不同的策略而已. 对于理解操作系统的工作机制 ...

  6. macos下使用rvm管理ruby版本和rails版本

    1. 安装rvm curl -L https://get.rvm.io | bash -s stable 查看rvm 版本 2. 安装ruby rvm install 2.3.1 查看ruby 版本 ...

  7. Contact Form 7邮件发送失败的解决办法

    一.contact form 7无法发送邮件的原因 对mail()函数的不支持. Contact Form 7表单提交失败在使用过程中会出现,归根结底原因在于wordpress主机问题,由于国 内很多 ...

  8. WPF combobox 圆角制作

    修改ComboBox的Template, 在VS 2010或者Blend中你可以导出ComboBox的默认模板: VS2010中: 然后修改里面的模板,比如: <Window x:Class=& ...

  9. vmware9.0 安装ios10.8应该注意的地方

    今天终于在我的thinkpad t400上面按照好了ios系统 我的硬件配置:cpu:p8700,内存:ddr3,6g 安装的版本:ios10.8 vmware的版本是vmware9.0 安装好的io ...

  10. 【转】cocos2d-x使用第三方的TTF字体库

    步骤一:找一个ttf字体库 步骤二:找到这个ttf字体库的真实名称 打开你的应用 "字体册"(MAC OS系统下),如下图操作): 找到了字体库真实名称,那么修改将其真名作为为此新 ...