最近在开发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类