Files
1440WGJ/SimpleServer/Client.cs
T

280 lines
9.0 KiB
C#
Raw Normal View History

2026-07-14 13:55:17 +08:00
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Windows.Forms;
namespace SimpleCommunication
{
public class Client : IDisposable
{
#region DataMember & Ctor
public 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<string> RecvMsgEvent;
public event DlgOneParam<string> RemoteDisconnectEvent;
public event DlgNoParam LocalDisconnectEvent;
/// <summary>
/// 客户端是否链接
/// </summary>
public bool IsConnected => (tcpclient != null && tcpclient.Connected) ? true : false;
/// <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(string msg)
{
bool result = false;
try
{
if (netstream != null)
{
if (!string.IsNullOrEmpty(msg))
{
byte[] buff = Encoding.Default.GetBytes(msg);
netstream.Write(buff, 0, buff.Length);
result = true;
}
}
}
catch (Exception ex)
{
throw ex;
}
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
{
string recvStr = "";
int count = netstream.EndRead(ar);
if (count > 0)
{
recvStr = Encoding.Default.GetString(readBytes, 0, count);
recvStr = DateTime.Now.ToString("HH:mm:ss") + " [" + IP + " " + Port + "] :\n" + recvStr + "\n";
if (RecvMsgEvent != null)
{
RecvMsgEvent(recvStr);
}
readBytes = new byte[tcpclient.ReceiveBufferSize];
netstream.BeginRead(readBytes, 0, readBytes.Length, EndRead, null);
}
else//远程客户端主动断开
{
LocalClientClose();
}
}
catch (Exception ex)
{
if (ex.Message.Contains("无法从传输连接中读取数据: 远程主机强迫关闭了一个现有的连接"))
{
LocalClientClose();
}
else
{
LocalClientClose();
}
}
}
}
}
#endregion
#region 客户端连接和关闭
/// <summary>
/// 客户端的client连接服务器
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <returns></returns>
public bool Connect(ComboBox Server_IP, TextBox txtPort)
{
bool result = false;
try
{
if (!string.IsNullOrEmpty(Server_IP.Text) && !string.IsNullOrEmpty(txtPort.Text))
{
IP = Server_IP.Text.Trim();
Port = txtPort.Text.Trim();
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();
BeginRead();
closed = false;
result = true;
}
}
catch (Exception ex)
{
if (ex.Message.Contains("由于目标计算机积极拒绝"))
{
if (ConnectFailEvent != null)
{
ConnectFailEvent();
}
}
else
{
}
}
return result;
}
/// <summary>
/// 远程连接断开后(点关闭断开,程序退出断开)本地连接处理
/// </summary>
public 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
}
/// <数据结构类>
/// 数据结构类
/// </数据结构类>
public class StateObject
{
//客户端Socket
public Socket workSocket = null;
//接收数据大小
public const int BufferSize = 64;
// 声明接收数据
public byte[] buffer = new byte[BufferSize];
// 接收数据的内容
public StringBuilder sb = new StringBuilder();
/// <summary>
/// 通信方网络地址
/// </summary>
public EndPoint SEndPoint;
}
}