using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ServerSocket
{
public class ClientState
{
private byte[] byteBuffer;
private Socket clientSocket;
public byte[] ByteBuffer
{
get { return byteBuffer; }
set { byteBuffer = value; }
}
public Socket ClientSocket
{
get { return clientSocket; }
set { clientSocket = value; }
}
public ClientState(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ServerSocket
{
public class ServerHandle
{
//ip地址
private string ip;
//端口号
private int port;
//服务端socket
private Socket serverSocket;
private List<ClientState> clientStatesList = new List<ClientState>();
/// <summary>
/// ip地址
/// </summary>
public string IP { get; set; }
/// <summary>
/// 端口号
/// </summary>
public int Port { get; set; }
/// <summary>
/// 服务端socket
/// </summary>
public Socket ServerSocket { get; set; }
/// <summary>
/// 构造方法
/// </summary>
/// <param name="ip">ip地址</param>
/// <param name="port">端口号</param>
public ServerHandle(string ip, int port)
{
this.ip = ip;
this.port = port;
}
/// <summary>
/// 开启服务器
/// </summary>
/// <param name="maxCount">设置最大同时监听个数</param>
public void StartServer(int maxCount)
{
Message("开启服务器");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = IPAddress.Any;
IPEndPoint endPoint = new IPEndPoint(address, port);
serverSocket.Bind(endPoint);
serverSocket.Listen(maxCount);
//异步处理用户上线
serverSocket.BeginAccept(new AsyncCallback(AcceptHandler), serverSocket);
}
/// <summary>
/// 处理用户上线
/// </summary>
/// <param name="asyncResult"></param>
private void AcceptHandler(IAsyncResult asyncResult)
{
Socket sreverSocket = (Socket)asyncResult.AsyncState;
Socket clientSocket = sreverSocket.EndAccept(asyncResult);
Message($"{clientSocket.RemoteEndPoint.ToString()}用户上线");
ClientState clientState = new ClientState(clientSocket);
clientStatesList.Add(clientState);
clientState.ByteBuffer = new byte[serverSocket.ReceiveBufferSize];
clientState.ClientSocket.BeginReceive(clientState.ByteBuffer, 0,
clientState.ByteBuffer.Length, 0,
new AsyncCallback(ReceiveHandler), clientState);
//继续监听下一个用户的上线请求.
sreverSocket.BeginAccept(new AsyncCallback(AcceptHandler), sreverSocket);
}
/// <summary>
/// 接收到客户端发送过来的消息之后的回调方法.
/// </summary>
/// <param name="asyncResult"></param>
private void ReceiveHandler(IAsyncResult asyncResult)
{
ClientState clientState = (ClientState)asyncResult.AsyncState;
Socket clientSocket = clientState.ClientSocket;
//写法1:下面的写法关闭客户端时会抛异常,原因未知
//int count = clientSocket.EndReceive(asyncResult);
//if (count == 0)
//{
// Message($"{clientSocket.RemoteEndPoint.ToString()}客户端已下线.");
// clientStatesList.Remove(clientState);
// return;
//}
int count = 0;
//写法2:
try
{
count = clientSocket.EndReceive(asyncResult);
}
catch (Exception)
{
Message($"客户端:{clientSocket.RemoteEndPoint.ToString()}已下线.");
clientStatesList.Remove(clientState);
return;
}
//转码成字符串.
string str = Encoding.UTF8.GetString(clientState.ByteBuffer, 0, count);
Message($"收到客户端{clientSocket.RemoteEndPoint.ToString()}的消息{str}");
//重置字节数组.
clientState.ByteBuffer = new byte[serverSocket.ReceiveBufferSize];
//接收下一条数据.
clientSocket.BeginReceive(clientState.ByteBuffer, 0,
clientState.ByteBuffer.Length, 0,
new AsyncCallback(ReceiveHandler), clientState);
}
/// <summary>
/// 关闭服务器
/// </summary>
/// <param name="socket">服务器的socket</param>
private void CloseServer()
{
foreach (var clientSocket in clientStatesList)
{
clientSocket.ClientSocket.Close();
}
serverSocket.Close();
Message("服务器端已关闭");
}
/// <summary>
/// 发送消息至客户端
/// </summary>
/// <param name="clientSocket">客户端的socket</param>
/// <param name="text">消息</param>
private void SendMsgToCLient(Socket clientSocket, string text)
{
byte[] message = Encoding.UTF8.GetBytes(text);
clientSocket.BeginSend(message, 0, message.Length, 0,
new AsyncCallback(SendHandler), clientSocket);
}
/// <summary>
/// 消息发送成功之后的回调方法
/// </summary>
/// <param name="asyncResult"></param>
private void SendHandler(IAsyncResult asyncResult)
{
Socket clientSocket = (Socket)asyncResult.AsyncState;
int count = clientSocket.EndSend(asyncResult);
Message($"{clientSocket?.RemoteEndPoint.ToString()}" +
$"消息发送成功,长度为:{count}");
}
/// <summary>
/// 发送消息至所有客户端
/// </summary>
/// <param name="text">消息</param>
public void SendAll(string text)
{
foreach (var clientState in clientStatesList)
{
SendMsgToCLient(clientState.ClientSocket, text);
}
}
/// <summary>
/// 消息调试
/// </summary>
/// <param name="str"></param>
private void Message(string str)
{
Console.WriteLine("MESSAGE:" + str);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ServerSocket
{
internal class Program
{
static void Main(string[] args)
{
int port = 8885;
ServerHandle serverHandle = new ServerHandle("127.0.0.1", port);
serverHandle.StartServer(100);
while (true)
{
string str = Console.ReadLine();
if (str == "a")
{
serverHandle.SendAll("向所有的客户端发消息");
}
}
Console.ReadKey();
}
}
}