/// <summary> /// 利用特定的端口与UDP服务端连接 /// </summary> /// <param name="server">UDP服务端IP</param> /// <param name="portStr">端口号</param> /// <returns>假如建立连接成功,返回1,否则返回0</returns> public static int Connect(string server, int port) { //尝试建立连接 int result = 1; try { //假如UDP主机客户端对象为空,则初始化 //if (Client == null) // Client = new UdpClient(new IPEndPoint(IPAddress.Parse(HostName), HostPort)); Client = new UdpClient(new IPEndPoint(IPAddress.Parse(HostName), HostPort)); ServerEndPoint = new IPEndPoint(IPAddress.Parse(server), port); Client.Connect(ServerEndPoint); ServerIp = server; //待连接的UDP主机IP地址 ServerPort = port; //待连接的UDP主机端口 IsConnected = true; //IsConnected = true; } catch (Exception e) { LastErrorMessage = string.Format("无法建立UDP连接:{0}", e.Message); FileClient.WriteExceptionInfo(e, LastErrorMessage, false); ////IP地址,端口重置 //ServerIp = string.Empty; //ServerPort = 0; //IsConnected = false; result = 0; throw; //假如不需要抛出异常,注释此行 } return(result); }
/// <summary> /// 从UDP主机接收信息并转换为字符串 /// </summary> /// <returns></returns> public static string ReceiveInfo() { try { //接收信息并转换为字符串 IPEndPoint endPoint = ServerEndPoint; byte[] buffer = Client.Receive(ref endPoint); //接收UDP主机发送的信息 string info = System.Text.Encoding.ASCII.GetString(buffer).Trim('\0'); //去除字符串头尾的空白字符 if (info == null || info.Length == 0) { return(string.Empty); } //(根据正文开始、正文结束字符)从字符串中截取正式信息 //信息开始处字符的索引,假如有正文开始字符,索引为该字符索引+1,否则为0 int startIndex = info.Contains(Base.STX) ? info.IndexOf(Base.STX) : 0; //信息中包含的字符数量 int length = info.Contains(Base.ETX) ? info.IndexOf(Base.ETX) - startIndex : info.Length - startIndex; info = info.Substring(startIndex, length); return(info); } catch (Exception e) { LastErrorMessage = "信息接收失败:" + e.Message; FileClient.WriteExceptionInfo(e, LastErrorMessage, false); throw; //如果不需要抛出异常,注释此行 } }
/// <summary> /// 从Tcp服务端获取信息的回调函数 /// </summary> /// <param name="ar"></param> private void TcpCallBack(IAsyncResult ar) { DerivedTcpClient client = (DerivedTcpClient)ar.AsyncState; NetworkStream ns = client.NetStream; try { byte[] recdata = new byte[ns.EndRead(ar)]; Array.Copy(client.Buffer, recdata, recdata.Length); //receivedEventArgs.ReceivedData = recdata; //receivedEventArgs.ReceivedInfo = HexHelper.ByteArray2HexString if (recdata.Length > 0) { if (DataReceived != null) { DataReceived.BeginInvoke(client.Name, new Events.DataReceivedEventArgs(recdata), null, null); //异步输出数据 } raiser.Click(); if (ReceiveRestTime > 0) { Thread.Sleep(ReceiveRestTime); } if (AutoReceive) { ns.BeginRead(client.Buffer, 0, client.Buffer.Length, new AsyncCallback(TcpCallBack), client); } } } catch (Exception ex) { FileClient.WriteExceptionInfo(ex, string.Format("从TcpServer获取数据的过程中出错:IP地址{0},端口{1}", ServerIp, ServerPort), true); } }
/// <summary> /// 从Tcp服务端获取信息的回调函数 /// </summary> /// <param name="ar"></param> private void ReceiveCallBack(IAsyncResult ar) { DerivedUdpClient client = (DerivedUdpClient)ar.AsyncState; try { //IPEndPoint point = RemoteEndPoint; byte[] recdata = BaseClient.EndReceive(ar, ref remote_endpoint); //RemoteEndPoint = point; if (recdata.Length > 0) { if (DataReceived != null) { DataReceived.BeginInvoke(client.Name, new Events.DataReceivedEventArgs(recdata), null, null); //异步输出数据 } raiser.Click(); if (ReceiveRestTime > 0) { Thread.Sleep(ReceiveRestTime); } if (AutoReceive) { BaseClient.BeginReceive(new AsyncCallback(ReceiveCallBack), client); } } } catch (Exception ex) { FileClient.WriteExceptionInfo(ex, string.Format("从TcpServer获取数据的过程中出错:IP地址{0},端口{1}", ServerIp, ServerPort), true); } }
/// <summary> /// 从Tcp服务端获取信息的回调函数 /// </summary> /// <param name="ar"></param> private void SocketCallBack(IAsyncResult ar) { DerivedTcpClient client = (DerivedTcpClient)ar.AsyncState; NetworkStream ns = client.NetStream; try { byte[] recdata = new byte[ns.EndRead(ar)]; Array.Copy(client.Buffer, recdata, recdata.Length); //this.receivedEventArgs.ReceivedData = recdata; //this.receivedEventArgs.ReceivedInfo = HexHelper.ByteArray2HexString if (recdata.Length > 0) { if (this.DataReceived != null) { this.DataReceived.BeginInvoke(client.Name, new CommonLib.Events.DataReceivedEventArgs(recdata), null, null); //异步输出数据 } ns.BeginRead(client.Buffer, 0, client.Buffer.Length, new AsyncCallback(SocketCallBack), client); } } catch (Exception ex) { FileClient.WriteExceptionInfo(ex, string.Format("从TcpServer获取数据的过程中出错:IP地址{0},端口{1}", this.ServerIp, this.ServerPort), true); } }
/// <summary> /// UDP重新连接方法 /// </summary> private void TcpAutoReconnect() { while (true) { Thread.Sleep(1000); //假如属性提示未连接,则UDP重连线程挂起 if (!IsConnected) { Auto_UdpReconnect.WaitOne(); } //假如属性提示已连接但实际上连接已断开,尝试重连 //else if (IsConnected && !IsSocketConnected()) else if (IsConnected && !IsConnected_Socket) { string temp = string.Format("UDP主机地址:{0},端口号:{1}", ServerIp, ServerPort); //UDP连接的主机地址与端口 LastErrorMessage = "UDP连接意外断开,正在尝试重连。" + temp; FileClient.WriteFailureInfo(LastErrorMessage); try { BaseClient.Close(); BaseClient = HoldLocalPort ? new UdpClient(LocalEndPoint) : new UdpClient(); BaseClient.Connect(ServerIp, ServerPort); SetName(); //重连次数+1,同时调用事件委托 ReconnTimer++; if (ReconnTimerChanged != null) { ReconnTimerChanged.BeginInvoke(Name, ReconnTimer, null, null); } if (Connected != null) { Connected.BeginInvoke(Name, new EventArgs(), null, null); } //NetStream = BaseClient.GetStream(); if (AutoReceive) { BaseClient.BeginReceive(new AsyncCallback(ReceiveCallBack), this); } //NetStream.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(TcpCallBack), this); //IsSocketConnected(); FileClient.WriteFailureInfo("UDP重新连接成功。" + temp); } //假如出现异常,将错误信息写入日志并进入下一次循环 catch (Exception e) { LastErrorMessage = string.Format("UDP重新连接失败:{0}。", e.Message) + temp; FileClient.WriteExceptionInfo(e, LastErrorMessage, false); continue; //TODO: 是否抛出异常? //throw; //假如不需要抛出异常,注释此句 } } } }
/// <summary> /// 向设备发送指令,接收设备返回的指令或错误信息 /// </summary> /// <param name="command">指令</param> /// <returns>返回发送的字节数</returns> public static void SendCommand(string command) { try { //转换为byte类型数组并发送指令 byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Base.STX + command + Base.ETX); //将字符串转换为byte数组 Client.Send(bytes, bytes.Length); } catch (Exception e) { LastErrorMessage = "指令发送失败:" + e.Message; FileClient.WriteExceptionInfo(e, LastErrorMessage, false); throw; //如果不需要抛出异常,注释此行 } }
/// <summary> /// 接受TCP客户端连接的回调函数 /// </summary> /// <param name="asyncResult"></param> private void TcpClientAcceptCallBack(IAsyncResult asyncResult) { TcpListener listener = (TcpListener)asyncResult.AsyncState; TcpClient client = listener.EndAcceptTcpClient(asyncResult); this.ClientList.Add(client); try { NetworkStream stream = client.GetStream(); stream.BeginRead(this.Buffer, 0, this.ReceiveBufferSize, new AsyncCallback(this.SocketCallBack), client); } catch (Exception ex) { //this.LastErrorMessage = string.Format("从TCP客户端{0}异步获取数据时出错: {1}", client.ToString()); FileClient.WriteExceptionInfo(ex, string.Format("从Tcp客户端异步获取数据时出错:IP{0},端口{1}", this.ServerIp, this.ServerPort), true); } }
/// <summary> /// 关闭连接 /// </summary> /// <returns>假如关闭成功,返回1,否则返回0</returns> public int Close() { string _class = MethodBase.GetCurrentMethod().ReflectedType.FullName; //命名空间+类名 string _method = string.Format("Int32 {0}", new StackTrace().GetFrame(0).GetMethod().Name); //方法名称 //假如未连接,返回错误信息 if (!this.IsConnected) { LastErrorMessage = "并未与任何主机建立连接,无需断开连接!"; FileClient.WriteFailureInfo(new string[] { LastErrorMessage, string.Format("类名称:{0},方法名称:{1}", _class, _method) }); return(0); } LastErrorMessage = string.Empty; int result = 1; if (ConnType == ConnTypes.TCP) { try { result = this.TcpClient.Close(); ServerIp = this.TcpClient.ServerIp; ServerPort = this.TcpClient.ServerPort; IsConnected = this.TcpClient.IsConnected; } catch (Exception) { LastErrorMessage = this.TcpClient.LastErrorMessage; throw; } } //TODO 编写其它连接方式的断开方法 else { //try //{ // result = BaseUdpClient.Close(); // ServerIp = BaseUdpClient.ServerIp; // ServerPort = BaseUdpClient.ServerPort; // IsConnected = BaseUdpClient.IsConnected; //} //catch (Exception) { LastErrorMessage = BaseUdpClient.LastErrorMessage; throw; } } ConnType = result == 1 ? ConnTypes.UNCONNECTED : ConnType; return(result); }
/// <summary> /// 发送字符串 /// </summary> /// <param name="content">字符串</param> /// <param name="endPoint">远程IP终结点</param> public void SendString(string content, IPEndPoint endPoint) { ////假如未连接,退出方法 //if (/*!IsConnected || */!IsSocketConnected() || string.IsNullOrEmpty(content)) // return; try { //转换为byte类型数组并发送指令 byte[] bytes = System.Text.Encoding.ASCII.GetBytes(content);//将字符串转换为byte数组 BaseClient.Send(bytes, bytes.Length, endPoint); } catch (Exception e) { LastErrorMessage = "字符串发送失败:" + e.Message; FileClient.WriteExceptionInfo(e, LastErrorMessage, false); throw; //如果不需要抛出异常,注释此行 } }
/// <summary> /// 发送字符串 /// </summary> /// <param name="content">字符串</param> public void SendString(string content) { //假如未连接,退出方法 if (!IsConnected || !IsSocketConnected() || string.IsNullOrEmpty(content)) { return; } try { //转换为byte类型数组并发送指令 byte[] bytes = System.Text.Encoding.ASCII.GetBytes(content);//将字符串转换为byte数组 NetStream.Write(bytes, 0, bytes.Length); } catch (Exception e) { LastErrorMessage = "字符串发送失败:" + e.Message; FileClient.WriteExceptionInfo(e, LastErrorMessage, false); throw; //如果不需要抛出异常,注释此行 } }
///// <summary> ///// 更新并返回TcpClient的连接状态 ///// </summary> ///// <returns>假如处于连接状态,返回true,否则返回false</returns> //public bool IsSocketConnected() //{ // //return IsConnected_Socket = (BaseClient != null && BaseClient.IsSocketConnected()); // return IsConnected_Socket; //} /// <summary> /// 关闭UDP连接 /// </summary> /// <returns>假如关闭成功,返回1,否则返回0</returns> public int Close() { LastErrorMessage = string.Empty; int result = 1; try { if (BaseClient != null) { ThreadAbort(); //终止重连线程 //关闭流并释放资源 //NetStream.Close(); //NetStream.Dispose(); BaseClient.Close(); IsStartListening = false; ServerIp = null; ServerPort = 0; IsConnected = false; //IsConnected_Socket = false; //调用连接断开事件委托 if (Disconnected != null) { Disconnected.BeginInvoke(Name, new EventArgs(), null, null); } BaseClient.Close(); BaseClient = null; } } catch (Exception e) { LastErrorMessage = string.Format("关闭UDP连接{0}失败:{1}", Name, e.Message); FileClient.WriteExceptionInfo(e, LastErrorMessage, false); result = 0; throw; //假如不需要抛出异常,注释此行 } return(result); }
/// <summary> /// TCP客户端以byte数组或16进制格式字符串发送数据 /// </summary> /// <param name="data_origin">待发送数据,byte数组或16进制格式字符串</param> /// <param name="errorMessage">返回的错误信息,假如未报错则为空</param> /// <returns>返回发送结果</returns> public bool SendData(object data_origin, out string errorMessage) { errorMessage = string.Empty; if (!IsConnected || !IsSocketConnected()) { errorMessage = string.Format("TCP服务端{0}未连接", Name); if (logging) { FileClient.WriteFailureInfo(errorMessage); } return(false); } byte[] data; string typeName = data_origin.GetType().Name; if (typeName == "Byte[]") { data = (byte[])data_origin; } else if (typeName == "String") { data = HexHelper.HexString2Bytes((string)data_origin); } else { errorMessage = string.Format("数据格式不正确({0}),无法向TCP服务端{1}发送数据", typeName, Name); FileClient.WriteFailureInfo(errorMessage); return(false); } try { NetStream.Write(data, 0, data.Length); } catch (Exception ex) { errorMessage = string.Format("向TCP服务端{0}发送数据失败 {1}", Name, ex.Message); FileClient.WriteExceptionInfo(ex, errorMessage, false); //MessageBox.Show(selClient.Name + ":" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } return(true); }
/// <summary> /// 从TCP服务端接收信息并转换为字符串 /// </summary> /// <returns>返回从TCP服务器接收到的信息</returns> public string ReceiveInfo() { //假如未连接,返回空字符串 if (!IsConnected || !IsSocketConnected()) { return(string.Empty); } try { //接收信息并转换为字符串 byte[] buffer = new byte[ReceiveBufferSize]; NetStream.Flush(); //不知道有没有用 NetStream.Read(buffer, 0, buffer.Length); string info = System.Text.Encoding.ASCII.GetString(buffer).Trim('\0'); //去除字符串头尾的空白字符 if (info == null || info.Length == 0) { return(string.Empty); } //(根据正文开始、正文结束字符)从字符串中截取正式信息 //信息开始处字符的索引,假如有正文开始字符,索引为该字符索引+1,否则为0 int startIndex = info.Contains(Base.STX) ? info.IndexOf(Base.STX) : 0; //信息中包含的字符数量 int length = info.Contains(Base.ETX) ? info.IndexOf(Base.ETX) - startIndex : info.Length - startIndex; info = info.Substring(startIndex, length); return(info); } //假如出现异常,将错误信息记入日志并返回空字符串 catch (Exception e) { LastErrorMessage = "信息接收失败:" + e.Message; FileClient.WriteExceptionInfo(e, LastErrorMessage, false); return(string.Empty); throw; //如果不需要抛出异常,注释此行 } }
/// <summary> /// 关闭UDP连接 /// </summary> /// <returns>假如关闭成功,返回1,否则返回0</returns> public static int Close() { //string _class = MethodBase.GetCurrentMethod().ReflectedType.FullName; //命名空间+类名 //string _method = string.Format("Int32 {0}", new StackTrace().GetFrame(0).GetMethod().Name); //方法名称 ////假如未连接,返回错误信息 //if (!IsConnected) //{ // LastErrorMessage = "并未与任何主机建立UDP连接,无需断开连接!"; // DataClient.WriteFailureInfo(new string[] { LastErrorMessage, string.Format("类名称:{0},方法名称:{1}", _class, _method) }); // return 0; //} LastErrorMessage = string.Empty; int result = 1; try { if (Client != null && IsConnected) { //关闭流并释放资源 Client.Close(); // Close Client ServerIp = string.Empty; ServerPort = 0; ServerEndPoint = null; IsConnected = false; } } catch (Exception e) { LastErrorMessage = string.Format("关闭UDP连接失败:{0}", e.Message); FileClient.WriteExceptionInfo(e, LastErrorMessage, false); result = 0; throw; //假如不需要抛出异常,注释此行 } return(result); }
/// <summary> /// UDP客户端以byte数组或16进制格式字符串发送数据 /// </summary> /// <param name="data_origin">待发送数据,byte数组或16进制格式字符串</param> /// <param name="endPoint">远程IP终结点</param> /// <param name="errorMessage">返回的错误信息,假如未报错则为空</param> /// <returns>返回发送结果</returns> public bool SendData(object data_origin, IPEndPoint endPoint, out string errorMessage) { errorMessage = string.Empty; //if (!IsConnected || !IsSocketConnected()) //{ // errorMessage = string.Format("UDP服务端{0}未连接", Name); // if (logging) // FileClient.WriteFailureInfo(errorMessage); // return false; //} byte[] data; string typeName = data_origin.GetType().Name; if (typeName == "Byte[]") { data = (byte[])data_origin; } else if (typeName == "String") { data = HexHelper.HexString2Bytes((string)data_origin); } else { errorMessage = string.Format("数据格式不正确({0}),无法向UDP服务端{1}发送数据", typeName, Name); FileClient.WriteFailureInfo(errorMessage); return(false); } try { BaseClient.Send(data, data.Length, endPoint); } catch (Exception ex) { errorMessage = string.Format("向UDP服务端{0}发送数据失败 {1}", Name, ex.Message); FileClient.WriteExceptionInfo(ex, errorMessage, false); return(false); } return(true); }
/// <summary> /// 通讯连接 /// </summary> /// <param name="serverIp">待连接的主机地址(IP地址)</param> /// <param name="portStr">待连接的端口号</param> /// <param name="connType">连接类型(UDP, TCP)</param> /// <returns>假如连接成功,返回1,否则返回0</returns> public int Connect(string serverIp, string portStr, ConnTypes connType) { string _class = MethodBase.GetCurrentMethod().ReflectedType.FullName; //命名空间+类名 string _method = string.Format("Int32 {0}", new StackTrace().GetFrame(0).GetMethod().Name); //方法名称 string connTypeName = Enum.GetName(typeof(ConnTypes), (int)connType); //连接类型的名称 //假如已连接,返回错误信息 if (IsConnected) { LastErrorCode = "001"; LastErrorMessage = string.Format("已与主机 {0} 在端口 {1} 建立{2}连接,无法再次连接!", ServerIp, ServerPort.ToString(), connTypeName); FileClient.WriteFailureInfo(new string[] { LastErrorMessage, string.Format("类名称:{0},方法名称:{1}", _class, _method) }); return(0); } //假如两个参数中有一个参数为空,则生成错误信息并抛出异常 string param = string.Empty; //参数名称 if (string.IsNullOrWhiteSpace(serverIp)) { param = "string serverIp"; LastErrorCode = "002"; LastErrorMessage = string.Format("建立{0}连接的主机地址不得为空!", connTypeName); } else if (string.IsNullOrWhiteSpace(portStr)) { param = "string portStr"; LastErrorCode = "003"; LastErrorMessage = string.Format("建立{0}连接的端口不得为空!", connTypeName); } if (!string.IsNullOrWhiteSpace(LastErrorCode)) { FileClient.WriteFailureInfo(new string[] { LastErrorMessage, string.Format("类名称:{0},方法名称:{1}", _class, _method) }); throw new ArgumentException(LastErrorMessage, param); //假如不需要抛出异常,注释此行 //return 0; } serverIp = serverIp.Equals("localhost", StringComparison.OrdinalIgnoreCase) ? "127.0.0.1" : serverIp; //判断localhost int port = int.Parse(portStr); //端口转换为数值类型 int result = 1; //判断连接类型并进行相应的连接,保存主机地址、端口与连接状态;假如报错,获取错误信息 if (connType == ConnTypes.TCP) { try { this.TcpClient = new DerivedTcpClient(serverIp, port); this.ServerIp = this.TcpClient.ServerIp; this.ServerPort = this.TcpClient.ServerPort; this.IsConnected = this.TcpClient.IsConnected; } catch (Exception) { this.LastErrorMessage = this.TcpClient.LastErrorMessage; throw; } } //TODO 编写其它连接方式的连接方法 else { //try //{ // result = BaseUdpClient.Connect(serverIp, port); // ServerIp = BaseUdpClient.ServerIp; // ServerPort = BaseUdpClient.ServerPort; // IsConnected = BaseUdpClient.IsConnected; //} //catch (Exception) { LastErrorMessage = BaseUdpClient.LastErrorMessage; throw; } } ConnType = connType; return(result); }
/// <summary> /// 利用特定的本地端口与TCP服务端连接 /// </summary> /// <param name="server">TCP服务端IP</param> /// <param name="port">端口号</param> /// <param name="localIp">本地IP</param> /// <param name="localPort">指定的本地端口(假如小于等于0则随机)</param> /// <returns>假如建立连接成功,返回1,否则返回0</returns> public int Connect(string server, int port, string localIp, int localPort) { //尝试建立连接 int result = 1; try { ServerIp = server; ServerPort = port; //BaseClient = new TcpClient(ServerIp, ServerPort); BaseClient = !string.IsNullOrWhiteSpace(localIp) && localPort > 0 ? new TcpClient(new IPEndPoint(IPAddress.Parse(localIp), localPort)) : new TcpClient(); BaseClient.Connect(ServerIp, ServerPort); SetName(); //修改连接名称 //重置重连次数,同时调用事件委托 ReconnTimer = 0; if (ReconnTimerChanged != null) { ReconnTimerChanged.BeginInvoke(Name, ReconnTimer, null, null); } BaseClient.ReceiveBufferSize = ReceiveBufferSize; //接收缓冲区的大小 NetStream = BaseClient.GetStream(); //发送与接收数据的数据流对象 raiser.Run(); } catch (Exception e) { LastErrorMessage = string.Format("无法建立TCP连接,IP{0},端口号{1}:{2}", ServerIp, ServerPort, e.Message); if (logging) { FileClient.WriteExceptionInfo(e, LastErrorMessage, false); } Close(); result = 0; throw; //假如不需要抛出异常,注释此行 } IsConnected = BaseClient.Connected; IsSocketConnected(); if (IsConnected) { //调用Tcp连接事件委托 if (Connected != null) { Connected.BeginInvoke(Name, (new EventArgs()), null, null); } if (Thread_TcpReconnect == null) { Auto_TcpReconnect = new AutoResetEvent(true); Thread_TcpReconnect = new Thread(new ThreadStart(TcpAutoReconnect)) { IsBackground = true }; //Thread_TcpReconnect.IsBackground = true; Thread_TcpReconnect.Start(); } else { Auto_TcpReconnect.Set(); } if (AutoReceive) { NetStream.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(TcpCallBack), this); } } return(result); }