20200126_BDDM_upperpc/SimpleServer/Client.cs
2023-07-27 10:53:17 +08:00

243 lines
7.8 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace SimpleServer
{
public class Client : IDisposable
{
#region DataMember & Ctor
private TcpClient tcpclient;
private NetworkStream netstream;
public string IP;
public string Port;
private byte[] readBytes;
private object tcpClientLock = new object();//锁TcpClient;Dispose之后就不允许EndRead远程连接断开以后就不允许再调用Dispose
private bool closed = false;//包括本地主动断开和远程断开
//在事务处理结束后才触发下列事件
public event DlgNoParam ConnectFailEvent;
public event DlgOneParam<string> NewClientEvent;
public event DlgOneParam<byte[]> RecvMsgEvent;
public event DlgOneParam<string> RemoteDisconnectEvent;
public event DlgNoParam LocalDisconnectEvent;
/// <summary>
/// 服务的client的构造函数
/// </summary>
/// <param name="tcpclient"></param>
public Client(TcpClient tcpclient)
{
this.tcpclient = tcpclient;
readBytes = new byte[tcpclient.ReceiveBufferSize];//接收数据的缓冲区大小,如果太小一段数据会多次接收完成
netstream = tcpclient.GetStream();//如果远程客户端断开一样可以获得netstream
}
/// <summary>
/// 客户端client的构造函数
/// </summary>
public Client()
{
}
#endregion
#region
/// <summary>
/// 在建立连接的情况下发送消息
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public bool SendMsg(byte[] msg)
{
bool result = false;
try
{
netstream.Write(msg, 0, msg.Length);
result = true;
}
catch
{
throw;
}
return result;
}
/// <summary>
/// 服务的接收到客户端连接后最先做的操作之一,客户端接收数据线程起始
/// </summary>
/// <returns></returns>
public bool BeginRead()
{
bool result = false;
try
{
IP = (tcpclient.Client.RemoteEndPoint as IPEndPoint).Address.ToString();
Port = (tcpclient.Client.RemoteEndPoint as IPEndPoint).Port.ToString();
if (NewClientEvent != null)
{
NewClientEvent(IP + " " + Port);
}
netstream.BeginRead(readBytes, 0, readBytes.Length, EndRead, null);//如果远程客户端断开这句话一样可以执行
result = true;
}
catch
{
throw;
}
return result;
}
/// <summary>
/// 有互斥资源
/// 接收数据远程连接断开远程程序关闭本地连接断开都会按顺序调用进来因为连接关闭后不再调用BeginRead
/// 服务器listener.stop时不会进入这个函数客户端照样通讯服务端只是不能接收新连接而已
/// </summary>
/// <param name="ar"></param>
private void EndRead(IAsyncResult ar)
{
lock (tcpClientLock)
{
if (!closed)//如果本地主动断开就不会进入
{
try
{
int count = netstream.EndRead(ar);
if (count > 0)
{
string recvStr = Encoding.Default.GetString(readBytes, 0, count);
recvStr = recvStr + "\r\n\r\n";
if (RecvMsgEvent != null)
{
RecvMsgEvent(readBytes);
}
readBytes = new byte[tcpclient.ReceiveBufferSize];
netstream.BeginRead(readBytes, 0, readBytes.Length, EndRead, null);
}
else//远程客户端主动断开
{
LocalClientClose();
}
}
catch (Exception ex)
{
if (ex.Message.Contains("无法从传输连接中读取数据: 远程主机强迫关闭了一个现有的连接"))
{
LocalClientClose();
}
else
{
throw;
}
}
}
}
}
#endregion
#region
/// <summary>
/// 客户端的client连接服务器
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <returns></returns>
public bool Connect(string ip, string port)
{
bool result = false;
try
{
ip = ip.Trim();
port = port.Trim();
if (!string.IsNullOrEmpty(ip) && !string.IsNullOrEmpty(port))
{
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint point = new IPEndPoint(ipAddress, int.Parse(port));
tcpclient = new TcpClient(AddressFamily.InterNetwork);
readBytes = new byte[tcpclient.ReceiveBufferSize];
tcpclient.Connect(point);
netstream = tcpclient.GetStream();
closed = false;
result = true;
}
}
catch (Exception ex)
{
if (ex.Message.Contains("由于目标机器积极拒绝,无法连接"))
{
if (ConnectFailEvent != null)
{
ConnectFailEvent();
}
}
else
{
}
}
return result;
}
/// <summary>
/// 远程连接断开后(点关闭断开,程序退出断开)本地连接处理
/// </summary>
private void LocalClientClose()
{
closed = true;
DisposeEx();
if (RemoteDisconnectEvent != null)
{
string param = IP + " " + Port;
if (RemoteDisconnectEvent != null)
{
RemoteDisconnectEvent(param);
}
}
}
/// <summary>
/// 有互斥资源
/// 在已连接条件下关闭本地连接和资源释放时调用
/// </summary>
public void Dispose()
{
lock (tcpClientLock)
{
if (!closed)
{
closed = true;
DisposeEx();
if (LocalDisconnectEvent != null)
{
LocalDisconnectEvent();
}
}
}
}
/// <summary>
/// 由Dispose和LocalClientClose调用
/// </summary>
private void DisposeEx()
{
if (netstream != null)
{
netstream.Dispose();
netstream = null;
}
if (tcpclient != null)
{
tcpclient.Close();
tcpclient = null;
}
}
#endregion
}
}