TCP Socket服务端客户端(二)
本文服务端客户端封装代码转自https://blog.csdn.net/zhujunxxxxx/article/details/44258719,并作了简单的修改。
1)服务端
此类主要处理服务端相关消息
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace TcpSocketServer
{
/// <summary>
/// Socket异步TCP服务器
/// 建议把close方法改为私有,即服务端不主动关闭连接
/// 客户端主动关闭连接后,其receive仍在
/// </summary>
public class TCPServerAsync : IDisposable
{
#region Fields
private int _maxClient;// 服务器程序允许的最大客户端连接数
private int _clientCount;// 当前的连接的客户端数
private Socket _serverSock;// 服务器使用的异步socket
private List<ClientInfo> _clients;// 客户端会话列表
private bool disposed = false;//内存释放
#endregion
#region Properties
public bool IsRunning { get; private set; }// 服务器是否正在运行
public IPAddress Address { get; private set; }// 监听的IP地址
public int Port { get; private set; }// 监听的端口
public Encoding Encoding { get; set; }// 通信使用的编码
#endregion
#region 构造函数
/// <summary>
/// 异步Socket TCP服务器
/// </summary>
public TCPServerAsync(int listenPort)
: this(IPAddress.Any, listenPort, 1024)
{
}
public TCPServerAsync(IPEndPoint localEP)
: this(localEP.Address, localEP.Port, 1024)
{
}
public TCPServerAsync(IPAddress localIPAddress, int listenPort, int maxClient)
{
this.Address = localIPAddress;
this.Port = listenPort;
this.Encoding = Encoding.Default;
_maxClient = maxClient;
_clients = new List<ClientInfo>();
_serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
#endregion
#region Method
/// <summary>
/// 启动服务器
/// </summary>
public void Start()
{
if (!IsRunning)
{
IsRunning = true;
_serverSock.Bind(new IPEndPoint(this.Address, this.Port));
_serverSock.Listen(1024);
_serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
}
}
/// <summary>
/// 启动服务器
/// </summary>
/// <param name="backlog">
/// 服务器所允许的挂起连接序列的最大长度
/// </param>
public void Start(int backlog)
{
if (!IsRunning)
{
IsRunning = true;
_serverSock.Bind(new IPEndPoint(this.Address, this.Port));
_serverSock.Listen(backlog);
_serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
}
}
/// <summary>
/// 停止服务器
/// </summary>
public void Stop()
{
if (IsRunning)
{
IsRunning = false;
_serverSock.Close();
//TODO 关闭对所有客户端的连接
CloseAllClient();
}
}
#region Close
/// <summary>
/// 关闭一个与客户端之间的会话
/// </summary>
/// <param name="state">需要关闭的客户端会话对象</param>
public void Close(ClientInfo state)
{
if (state != null)
{
//state.Datagram = null;
state.RecvDataBuffer = null;
_clients.Remove(state);
_clientCount--;
//TODO 触发关闭事件
state.Close();
}
}
/// <summary>
/// 关闭所有的客户端会话,与所有的客户端连接会断开
/// </summary>
public void CloseAllClient()
{
foreach (ClientInfo client in _clients)
{
Close(client);
}
_clientCount = 0;
_clients.Clear();
}
#endregion
/// <summary>
/// 处理客户端连接
/// </summary>
/// <param name="ar"></param>
private void HandleAcceptConnected(IAsyncResult ar)
{
if (IsRunning)
{
Socket server = (Socket)ar.AsyncState;
Socket client = server.EndAccept(ar);
//检查是否达到最大的允许的客户端数目
if (_clientCount >= _maxClient)
{
//C-TODO 触发事件
RaiseOtherException(null);
}
else
{
ClientInfo state = new ClientInfo(client);
lock (_clients)
{
_clients.Add(state);
_clientCount++;
RaiseClientConnected(state); //触发客户端连接事件
}
state.RecvDataBuffer = new byte[client.ReceiveBufferSize];
//开始接受来自该客户端的数据
client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,
new AsyncCallback(HandleDataReceived), state);
}
//接受下一个请求
server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);
}
}
/// <summary>
/// 处理客户端数据
/// </summary>
/// <param name="ar"></param>
private void HandleDataReceived(IAsyncResult ar)
{
if (IsRunning)
{
ClientInfo state = (ClientInfo)ar.AsyncState;
Socket client = state.ClientSocket;
try
{
//异步接收,当客户端退出的时候会再次执行EndReceive
int recv = client.EndReceive(ar);
//客户端主动断开连接时(采用close关闭)recv == 0
//所以执行回掉RaiseClientDisconnected,并在回掉函数中关闭连接
//以不在RaiseClientDisconnected回掉中关闭连接为优,即直接调用Close关闭
if (recv == 0)
{
//C- TODO 触发事件 (关闭客户端)
//Close(state);
RaiseClientDisconnected(state);
return;
}
//TODO 处理已经读取的数据 ps:数据在state的RecvDataBuffer中
state._recvdBufferLength = recv;
//C- TODO 触发数据接收事件
RaiseDataReceived(state);
}
catch (SocketException)
{
//C- TODO 异常处理
RaiseNetError(state);
//客户端主动断开连接时(直接关闭程序,而非采用close关闭)引发以尝
//所以执行回掉RaiseClientDisconnected,并在回掉函数中关闭连接
//以不在回掉中关闭连接为优,直接/Close(state)关闭
state._recvdBufferLength = 0;
RaiseClientDisconnected(state);
return;
}
//继续接收来自来客户端的数据
//ps: 如果未接收到数据则始终处于挂起状态;
//pss:当收到close消息,server主动关闭连接(212行RaiseDataReceived中进行了关闭)时由于已经关闭连接,所以下述代码会有异常
//后续可在应用只要不是通过客户端发消息主动close就可避免此问题,所以在此加一个异常处理,或者加一个bool变量判断是否断掉
try
{
client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,
new AsyncCallback(HandleDataReceived), state);
}
catch{}
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="state">接收数据的客户端会话</param>
/// <param name="data">数据报文</param>
public void Send(ClientInfo state, byte[] data)
{
RaisePrepareSend(state);
Send(state.ClientSocket, data);
}
/// <summary>
/// 异步发送数据至指定的客户端
/// </summary>
/// <param name="client">客户端</param>
/// <param name="data">报文</param>
public void Send(Socket client, byte[] data)
{
if (!IsRunning)
throw new InvalidProgramException("This TCP Scoket server has not been started.");
if (client == null)
throw new ArgumentNullException("client");
if (data == null)
throw new ArgumentNullException("data");
client.BeginSend(data, 0, data.Length, SocketFlags.None,
new AsyncCallback(SendDataEnd), client);
}
/// <summary>
/// 发送数据完成处理函数
/// </summary>
/// <param name="ar">目标客户端Socket</param>
private void SendDataEnd(IAsyncResult ar)
{
((Socket)ar.AsyncState).EndSend(ar);
RaiseCompletedSend(new TcpSocketServer.ClientInfo((Socket)ar.AsyncState));
}
#endregion
#region 事件
#region 客户端连接事件
public event EventHandler<TCPMessageArgs> ClientConnecting;//客户端正在连接事件
public event EventHandler<TCPMessageArgs> ClientConnected; //客户端连接事件
public event EventHandler<TCPMessageArgs> ClientDisconnected;//客户端断开连接
//挂起事件
private void RaiseClientConnecting(ClientInfo state)
{
if(ClientConnecting!=null)
{
ClientConnecting(this, new TCPMessageArgs(state));
}
}
private void RaiseClientConnected(ClientInfo state)
{
if (ClientConnected != null)
{
ClientConnected(this, new TCPMessageArgs(state));
}
}
private void RaiseClientDisconnected(ClientInfo state)
{
if (ClientDisconnected != null)
{
ClientDisconnected(this, new TCPMessageArgs(state));
}
}
#endregion
#region 数据发送事件
public event EventHandler<TCPMessageArgs> PrepareSend;//数据准备发送事件
public event EventHandler<TCPMessageArgs> DataSending;//数据正在发送事件
public event EventHandler<TCPMessageArgs> CompletedSend;//数据发送结束事件
public event EventHandler<TCPMessageArgs> DataReceived;//接受到客户端数据事件
//挂起事件
private void RaisePrepareSend(ClientInfo state)
{
if (PrepareSend != null)
{
PrepareSend(this, new TCPMessageArgs(state));
}
}
private void RaiseDataSending(ClientInfo state)
{
if (PrepareSend != null)
{
DataSending(this, new TCPMessageArgs(state));
}
}
private void RaiseDataReceived(ClientInfo state)
{
if (DataReceived != null)
{
DataReceived(this, new TCPMessageArgs(state));
}
}
private void RaiseCompletedSend(ClientInfo state)
{
if (CompletedSend != null)
{
CompletedSend(this, new TCPMessageArgs(state));
}
}
#endregion
#region 关闭连接事件
public event EventHandler<TCPMessageArgs> ClientClose;//关闭客户端事件
public event EventHandler<TCPMessageArgs> AllClientsClose;//关闭所有客户端事件
//挂起事件
private void RaiseClientClose(ClientInfo state)
{
if(ClientClose!=null)
{
ClientClose(this, new TcpSocketServer.TCPMessageArgs(state));
}
}
private void RaiseAllClientClose(ClientInfo state)
{
if (AllClientsClose != null)
{
AllClientsClose(this, new TcpSocketServer.TCPMessageArgs(state));
}
}
#endregion
#region 其他事件
public event EventHandler<TCPMessageArgs> NetError;// 网络错误事件
public event EventHandler<TCPMessageArgs> OtherException;//其他异常
//挂起事件
private void RaiseNetError(ClientInfo state)
{
if (OtherException != null)
{
OtherException(this, new TCPMessageArgs(state));
}
}
private void RaiseOtherException(ClientInfo state)
{
RaiseOtherException(state);
}
#endregion
#endregion
#region 释放
/// <summary>
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release
/// both managed and unmanaged resources; <c>false</c>
/// to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
try
{
Stop();
if (_serverSock != null)
{
_serverSock = null;
}
}
catch (SocketException)
{
//TODO
RaiseOtherException(null);
}
}
disposed = true;
}
}
#endregion
}
}
2)客户端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text; namespace TcpSocketClient
{
public class TCPClientAsync
{
#region 字段 private Socket clientSock; //private byte[] recvBuffer; private ClientInfo state; #endregion #region 属性 public IPAddress Address { get; private set; }// 监听的IP地址 public int Port { get; private set; }// 监听的端口
public bool IsConnected { get;private set; } #endregion #region 构造方法 public TCPClientAsync(IPAddress ipAddress,int port)
{
this.Address = ipAddress;
this.Port = port;
clientSock=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
} public TCPClientAsync(IPEndPoint ipEndPort)
:this(ipEndPort.Address,ipEndPort.Port)
{
} #endregion #region Method public void Connect()//开始连接
{
if(!IsConnected)
{
//clientSock.BeginConnect(Address, Port, new AsyncCallback(HandleConnectAccepted), clientSock);
clientSock.BeginConnect(Address, Port, iAsyncResult=>
{
try
{
clientSock.EndConnect(iAsyncResult);
IsConnected = true;
state = new TcpSocketClient.ClientInfo(clientSock);
RaiseConnectAccepted(state);//挂起连接事件
}
catch
{
//TODO连接失败
RaiseConnectFailed();
} }, null);
}
} //private void HandleConnectAccepted(IAsyncResult iAsyncResult)
//{
// clientSock.EndConnect(iAsyncResult);
// IsConnected = true;
//} public void Send(byte[] data)
{
if (!IsConnected) return; //clientSock.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(HandleDataSend), null);
clientSock.BeginSend(data, , data.Length, SocketFlags.None, iAsyncResult=>
{
clientSock.EndSend(iAsyncResult); RaiseDataSend(state);
}, null);
} public void Receive()
{
if (!IsConnected) return; state.RecvDataBuffer = new byte[clientSock.ReceiveBufferSize];
clientSock.BeginReceive(state.RecvDataBuffer, , state.RecvDataBuffer.Length, SocketFlags.None, new AsyncCallback(HandleDataReceive), null);
} private void HandleDataReceive(IAsyncResult iAsyncResult)
{
int recv = ;
try
{
recv = clientSock.EndReceive(iAsyncResult); if (recv == )//客户端主动断开连接时recv=0
{
Close();
RaiseServerCloseLink();
return;
} state._recvdBufferLength = recv; RaiseDataReceived(state);
}
catch(Exception ex)
{
//TODO 信息获取失败
string str = ex.Message;
return;
} //if (!IsConnected) return;
clientSock.BeginReceive(state.RecvDataBuffer, , state.RecvDataBuffer.Length, SocketFlags.None, new AsyncCallback(HandleDataReceive), null);
}
//private void HandleDataSend(IAsyncResult iAsyncResult)
//{
// clientSock.EndSend(iAsyncResult);
//} public void Close()
{
//关闭数据的接受和发送
clientSock.Shutdown(SocketShutdown.Both); //清理资源
clientSock.Close(); state = null;
IsConnected = false;
GC.Collect();
}
#endregion #region 事件 public event EventHandler<TCPMessageArgs> ConnectAccepted;//连接事件 public event EventHandler<TCPMessageArgs> DataSend;//数据发送事件 public event EventHandler<TCPMessageArgs> DataReceived;//数据发送事件 public event EventHandler<TCPMessageArgs> ErrorException;//错误信息 public event EventHandler<TCPMessageArgs> ServerCloseLink;//服务端关闭连接 public event EventHandler<TCPMessageArgs> ConnectFailed;//连接失败 private void RaiseConnectAccepted(ClientInfo state)
{
if (ConnectAccepted != null)
{
ConnectAccepted(this, new TCPMessageArgs(state));
}
} private void RaiseDataSend(ClientInfo state)
{
if (DataSend != null)
{
DataSend(this, new TcpSocketClient.TCPMessageArgs(state));
}
} private void RaiseDataReceived(ClientInfo state)
{
if(DataReceived!=null)
{
DataReceived(this, new TcpSocketClient.TCPMessageArgs(state));
}
} private void RaiseErrorException()
{
if(ErrorException!=null)
{
ErrorException(this, null);
}
} private void RaiseServerCloseLink()
{
if(ServerCloseLink!=null)
{
ServerCloseLink(this, null);
}
} private void RaiseConnectFailed()
{
if(ConnectFailed!=null)
{
ConnectFailed(this,null);
}
} #endregion
}
}
3)消息类
此类存储相关消息
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace TcpSocketServer
{
/// <summary>
/// Socket TCP事件参数
/// </summary>
public class TCPMessageArgs : EventArgs
{
/// <summary>
/// 提示信息
/// </summary>
public string _msg; /// <summary>
/// 客户端状态封装类
/// </summary>
public ClientInfo state; /// <summary>
/// 是否已经处理过了
/// </summary>
// public bool IsHandled { get; set; } public TCPMessageArgs(string msg)
{
this._msg = msg;
//IsHandled = false;
}
public TCPMessageArgs(ClientInfo state)
{
this.state = state;
// IsHandled = false;
}
public TCPMessageArgs(string msg, ClientInfo state)
{
this._msg = msg;
this.state = state;
//IsHandled = false;
}
}
}
4)服务端存储所有客户端类
通过
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml; namespace TcpSocketServer
{ /// <summary>
/// 客户端信息
/// </summary>
public class ClientInfo
{
#region 字段 public int _recvdBufferLength;//接收到的数据长度 private byte[] _recvBuffer;// 接收数据缓冲区 private string _datagram;// 客户端发送到服务器的报文 private Socket _clientSock;// 客户端的Socket private string tempMsg = string.Empty; #endregion #region 属性 /// <summary>
/// 接收数据缓冲区
/// </summary>
public byte[] RecvDataBuffer
{
get
{
return _recvBuffer;
}
set
{
_recvBuffer = value;
}
} /// <summary>
/// 存取会话的报文
/// </summary>
public string Datagram
{
get
{
_datagram = Encoding.Default.GetString(_recvBuffer, , _recvdBufferLength);
return _datagram;
}
} public List<MsgProtocol> MsgList
{
get
{
_datagram = Encoding.Default.GetString(_recvBuffer, , _recvdBufferLength);
return HandlerRecvdString(_datagram);
}
} /// <summary>
/// 获得与客户端会话关联的Socket对象
/// </summary>
public Socket ClientSocket
{
get
{
return _clientSock;
}
} #endregion public ClientInfo(Socket clientSocket)
{
_clientSock = clientSocket;
} public void Close()
{
//关闭数据的接受和发送
_clientSock.Shutdown(SocketShutdown.Both); //清理资源
_clientSock.Close();
} public List<MsgProtocol> HandlerRecvdString(string msg)
{
List<MsgProtocol> msgProList = new List<MsgProtocol>();
if (!String.IsNullOrEmpty(tempMsg))
{
msg = tempMsg + msg;
}
string pattern = "(^<protocol>.*?</protocol>)";
if (Regex.IsMatch(msg, pattern))
{
//匹配协议内容
string message = Regex.Match(msg, pattern).Groups[].Value;
//将匹配的内容添加到集合
msgProList.Add(HandleMsg(message));
tempMsg = string.Empty;
//截取未匹配字符串,进行下一次匹配
msg = msg.Substring(message.Length);
if (!String.IsNullOrEmpty(msg))
{
msgProList.AddRange(HandlerRecvdString(msg));
}
}
else
{
tempMsg = msg;
}
return msgProList;
} private MsgProtocol HandleMsg(string msg)
{
MsgProtocol msgProtocol = new TcpSocketServer.MsgProtocol(); XmlDocument xml = new XmlDocument();
xml.LoadXml(msg);
XmlNode node = xml.DocumentElement;
XmlNode message = node.FirstChild;// xml.SelectSingleNode("message"); if(message.Attributes["type"].Value==MsgType.TEXT.ToString())
{
TextProtocol text = new TcpSocketServer.TextProtocol(message.Attributes["content"].Value);
msgProtocol.type = MsgType.TEXT;
msgProtocol.textProtocol = text;
}
else
{
FileProtocol file = new TcpSocketServer.FileProtocol(message.Attributes["content"].Value, message.Attributes["file"].Value);
msgProtocol.type = MsgType.FILE;
msgProtocol.fileProtocol = file;
} return msgProtocol;
} }
}
5)消息协议
处理每次消息发送时粘包问题
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text; namespace TcpSocketServer
{
public enum MsgType
{
UNKNOWN = ,
TEXT = ,
FILE =
} public class TextProtocol
{
public string content; private MsgType type=MsgType.TEXT; public TextProtocol(string content)
{
this.content = content;
} //public byte[] ToBytes()
//{
// string msgPackage = ToString();
// return Encoding.Default.GetBytes(msgPackage);
//} public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("<message ");
sb.Append(string.Format("type=\"{0}\"", type.ToString()));
sb.Append(string.Format(" content=\"{0}\"", content));
sb.Append("/>"); return sb.ToString();
}
} public class FileProtocol
{
public string filePath; public string content; private string fileName; private MsgType type = MsgType.FILE; public FileProtocol(string content,string filePath)
{
this.filePath = filePath;
this.content = content;
} public FileProtocol(string filePath)
{
this.filePath = filePath;
} public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("<message ");
sb.Append(string.Format("type=\"{0}\"", type.ToString()));
sb.Append(string.Format(" file=\"{0}\"", GetFileName()));
sb.Append(string.Format(" content=\"{0}\"", GetFileContent()));
sb.Append("/>"); return sb.ToString();
} public byte[] ToBytes()
{
return Encoding.Default.GetBytes(content);
} private string GetFileName()
{
if(File.Exists(filePath))
{
return Path.GetFileName(filePath);
}
else
{
return "";
}
} private string GetFileContent()
{
if(File.Exists(filePath))
{
byte[] bytes = File.ReadAllBytes(filePath);
content = Encoding.Default.GetString(bytes);
} return content;
}
} public class MsgProtocol
{
//公共字段
//public string fileName;
public MsgType type = MsgType.UNKNOWN; public TextProtocol textProtocol; public FileProtocol fileProtocol; public MsgProtocol()
{ } public MsgProtocol(TextProtocol textProtocol)
{
this.type = MsgType.TEXT;
this.textProtocol = textProtocol;
} public MsgProtocol(FileProtocol fileProtocol)
{
this.type = MsgType.FILE;
this.fileProtocol = fileProtocol;
} public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("<protocol>"); if(type==MsgType.TEXT)
{
sb.Append(textProtocol.ToString());
}
else
{
sb.Append(fileProtocol.ToString());
} sb.Append("</protocol>"); return sb.ToString();
} public byte[] ToBytes()
{
return Encoding.Default.GetBytes(this.ToString());
} //public MsgProtocol(string filePath,MsgType type)
//{
// type = MsgType.FILE;
// this.fileName = fileName;
// this.file
//}
}
}
6)主程序应用
1、服务端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace TcpSocketServer
{
class Program
{
private static TCPServerAsync tcpServer; static void Main(string[] args)
{
tcpServer = new TcpSocketServer.TCPServerAsync(); tcpServer.DataReceived += new EventHandler<TcpSocketServer.TCPMessageArgs>(OnDataReceived);
tcpServer.ClientConnected += new EventHandler<TcpSocketServer.TCPMessageArgs>(OnClientConnected);
tcpServer.ClientDisconnected += new EventHandler<TcpSocketServer.TCPMessageArgs>(OnClientDisconnected); tcpServer.Start();
Console.ReadKey();
} public static void OnDataReceived(object obj,TCPMessageArgs message)
{
ClientInfo state = message.state;
string sendData = "Server "; //byte[] data = state.RecvDataBuffer;
//string strData = Encoding.Default.GetString(data); //Console.WriteLine(message.state.Datagram); #region 协议功能测试
List<MsgProtocol> msgList = state.MsgList; foreach (MsgProtocol msgProtocol in msgList)
{
if (msgProtocol.type == MsgType.TEXT)
{
Console.WriteLine(msgProtocol.textProtocol.content);
sendData += msgProtocol.textProtocol.content;
}
else
{
Console.WriteLine(msgProtocol.fileProtocol.filePath);
sendData += msgProtocol.fileProtocol.filePath;
} }
#endregion if (message.state.Datagram=="close")
{
tcpServer.Close(message.state);
return;
} //数据处理后发送回客户端
//string sendData = "Server " + message.state.Datagram;
//byte[] sendBytes = Encoding.Default.GetBytes(sendData);
//tcpServer.Send(state, sendBytes); #region 协议功能测试
MsgProtocol protocol = new TcpSocketServer.MsgProtocol(new TcpSocketServer.TextProtocol(sendData));
tcpServer.Send(state, protocol.ToBytes());
#endregion
} public static void OnClientConnected(object obj, TCPMessageArgs message)
{
Console.WriteLine("Connect:" + message.state.ClientSocket.RemoteEndPoint.ToString());
}
public static void OnClientDisconnected(object obj, TCPMessageArgs message)
{
Console.WriteLine("Disconnect:" + message.state.ClientSocket.RemoteEndPoint.ToString());
tcpServer.Close(message.state);
}
}
}
2、客户端调用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text; namespace TcpSocketClient
{
class Program
{
private static TCPClientAsync tcpclient;
private static bool b_Connecting = true; static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("192.168.8.15");
tcpclient = new TcpSocketClient.TCPClientAsync(ip, );
tcpclient.ConnectAccepted += new EventHandler<TcpSocketClient.TCPMessageArgs>(OnConnected);
tcpclient.DataReceived += new EventHandler<TcpSocketClient.TCPMessageArgs>(OnReceived);
tcpclient.ServerCloseLink += new EventHandler<TCPMessageArgs>(OnDisConnected);
tcpclient.Connect(); while(b_Connecting)
{
string msg = Console.ReadLine();
if(msg=="exit")
{
tcpclient.Close();
//b_Connecting = false;
break;
} if(msg=="close")
{
//tcpclient.IsConnected = false;
} //byte[] data = Encoding.Default.GetBytes(msg);
//tcpclient.Send(data);
//tcpclient.Receive(); MsgProtocol msgProtocol = new TcpSocketClient.MsgProtocol(new TcpSocketClient.TextProtocol(msg)); tcpclient.Send(msgProtocol.ToBytes());
}
} public static void OnConnected(object obj,TCPMessageArgs msg)
{
Console.WriteLine("Connected.......");
tcpclient.Receive();
} public static void OnReceived(object obj, TCPMessageArgs msg)
{
//Console.WriteLine("Receivedd "+msg.state.Datagram);
List<MsgProtocol> msgList = msg.state.MsgList; foreach(MsgProtocol msgProtocol in msgList)
{
if(msgProtocol.type==MsgType.TEXT)
{
Console.WriteLine(msgProtocol.textProtocol.content);
}
else
{
Console.WriteLine(msgProtocol.fileProtocol.filePath);
} }
} public static void OnDisConnected(object obj,TCPMessageArgs msg)
{
Console.WriteLine("Server Disconnected");
}
}
}
PS:未作客户端短线重连
TCP Socket服务端客户端(二)的更多相关文章
- TCP/IP网络编程之基于TCP的服务端/客户端(二)
回声客户端问题 上一章TCP/IP网络编程之基于TCP的服务端/客户端(一)中,我们解释了回声客户端所存在的问题,那么单单是客户端的问题,服务端没有任何问题?是的,服务端没有问题,现在先让我们回顾下服 ...
- TCP/IP网络编程之基于TCP的服务端/客户端(一)
理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于流(stream)的套接字.TCP是Transmissi ...
- Java中使用Socket连接判断Inputstream结束,java tcp socket服务端,python tcp socket客户端
最近在试着用java写一个socket的服务器,用python写一个socket的客户端来完成二者之间的通信,但是发现存在一个问题,服务器方面就卡在读取inputsream的地方不动了,导致后面的代码 ...
- java socket 服务端 客户端
Server package com.witwicky.socket.basicsocket; import java.io.IOException; import java.io.InputStre ...
- python 并发编程 socket 服务端 客户端 阻塞io行为
阻塞io行为 server.accept server.recv client.send recv,accept 分为两个阶段 1.wait for data 对方把数据经过网络延迟送到自己的操作系 ...
- C# Socket服务端与客户端通信(包含大文件的断点传输)
步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤: (1)建立一个Socket (2)接收 ...
- TCP/IP网络编程之基于UDP的服务端/客户端
理解UDP 在之前学习TCP的过程中,我们还了解了TCP/IP协议栈.在四层TCP/IP模型中,传输层分为TCP和UDP这两种.数据交换过程可以分为通过TCP套接字完成的TCP方式和通过UDP套接字完 ...
- 利用多线程使socket服务端可以与多个客户端同时通讯
利用多线程使socket服务端可以与多个客户端同时通讯 server import socket 1. 符合TCP协议的手机 server = socket.socket(socket.AF_INET ...
- 在python中编写socket服务端模块(二):使用poll或epoll
在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...
随机推荐
- 程序猿——踩bug之路
从开始这就是一个新的坑,还好今天我们爬上了: 带着Ui界面的编程,最想感谢的是我的搭档乔美萱:此处我觉得需要掌声和尖叫,一路带我从走到飞: 一.结对编程项目:带UI的小初高数学学习软件 1.用户注册功 ...
- 4.7 if else-if
c#中的if else-if if else-if 中最后的"else":如果用户输入的不等于上面的else if(xxx)表达式,则输出这行代码. **不参与运算的数值不用转换 ...
- Spring MVC-从零开始-view-forward、redirect
1.forward或redirect后,不再走viewResolver过程,直接重新从控制器开始 2.代码 package com.jt; import org.springframework.ste ...
- linux mint 19.2与Windows 10 双系统硬盘安装与卸载
安装linux mint 和win10双系统: 1.win10系统下如果没有空闲分区,请从容量较大的分区用partition manager在选中的较大的分区下,调整大小.此步骤最好在pe下的part ...
- ShaderHelper2 组件升级,支持自动枚举参数!
ShaderHelper2 组件新体验视频演示: https://www.bilibili.com/video/av69314195/ ShaderHelper2 组件我们已经介绍过两次了,不了解的伙 ...
- [Note] Visual Studio Team Service 中的项目 转到 Git
Git-tf是微软发布的一个Git工具集的补充,用来让开发人员使用git命令与TFS交互,当然现在VSTS已经直接支持git了,现在讲讲以前用了VSTS的老项目如何转到git,保留所有的change ...
- C语言I博客作业03
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-2/homework/8717 我在这个课程的目 ...
- [插件化开发] 1. 初识OSGI
初识 OSGI 背景 当前product是以solution的方式进行售卖,但是随着公司业务规模的快速夸张,随之而来的是新客户的产品开发,老客户的产品维护,升级以及修改bug,团队的效能明显下降,为了 ...
- VMware ESXI6.0服务器安装系列:U盘安装问题汇总之网卡驱动安装
本文转载至:http://blog.51cto.com/huanwenli/1749298 在给物理服务器安装ESXI的过程中经常会遇到网卡驱动问题,如果是买的是Dell.HP.IBM等厂商的服务器, ...
- php函数fsockopen的使用
函数说明:fsockopen — 打开一个网络连接或者一个Unix套接字连接 语法: resource fsockopen ( string $hostname [, int $port = -1 [ ...