服务端实现示例
一、最基础的服务端实现
实现的基本步骤: 1. 创建套接字Socket 2. 使用Bind方法将套接字和本地地址绑定 3. 使用Listen监听 4. 用Accept方法等待客户端链接 5. 建立链接,Accept返回新套接字 6. 使用Send和Receive相关方法收发数据 7. 使用Shutdown方法释放链接 8. 关闭套接字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| Socket socketTcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try { IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080); socketTcp.Bind(ipPoint); } catch (Exception e) { Console.WriteLine("绑定报错"+e.Message); return; }
socketTcp.Listen(1024); Console.WriteLine("服务端绑定监听结束,等待客户端连入");
Socket socketClient = socketTcp.Accept();
socketClient.Send(Encoding.UTF8.GetBytes("欢迎连入服务端"));
byte[] result = new byte[1024]; int receiveNum = socketClient.Receive(result); Console.WriteLine("接收到了{0},发来的消息:{1}", socketClient.RemoteEndPoint.ToString(), Encoding.UTF8.GetString(result,0,receiveNum));
socketClient.Shutdown(SocketShutdown.Both);
socketClient.Close(); #endregion
Console.WriteLine("按任意键推出"); Console.ReadKey();
|
二、服务多个客户端的基本实现
- 建立Socket 绑定 监听
- 等待客户端链接(主要实现服务多个客户端) 实现方向:多线程
- 收发消息
- 关闭相关
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| internal class Program { private static Socket _socket; static List<Socket> _clientSockets = new List<Socket>();
private static bool _isClosed = false; public static void Main(string[] args) { _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080); _socket.Bind(ipPoint); _socket.Listen(1024); Thread acceptThread = new Thread(AcccptClientConnection); acceptThread.Start(); Console.WriteLine("等待客户端链接"); Thread receiveThread = new Thread(receiveMessage); receiveThread.Start(); while (true) { string input = Console.ReadLine(); if (input == "Quit") { _isClosed = true; for (int i = 0; i < _clientSockets.Count; i++) { _clientSockets[i].Shutdown(SocketShutdown.Both); _clientSockets[i].Close(); } _clientSockets.Clear(); break; } } } private static void receiveMessage() { Socket clientSocket; byte[] result = new byte[1024 * 1024]; int receiveNum; while (!_isClosed) { for (int i = 0; i < _clientSockets.Count; i++) { clientSocket = _clientSockets[i]; if (clientSocket.Available > 0) { receiveNum = clientSocket.Receive(result); ThreadPool.QueueUserWorkItem(HandMessage, (clientSocket, Encoding.UTF8.GetString(result, 0, receiveNum))); }
} } } private static void HandMessage(object obj) { (Socket s, string str) info = ((Socket s, string str))obj; Console.WriteLine("收到客户端{0}发来的消息:{1}",info.s.RemoteEndPoint,info.str); }
public static void AcccptClientConnection() { while (!_isClosed) { Socket clientSocket = _socket.Accept(); _clientSockets.Add(clientSocket); clientSocket.Send(Encoding.UTF8.GetBytes("欢迎连入服务端")); } } }
|
三、面向对象的思想进行封装
1.服务端Socket
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| public class SeverSocket { public Socket socket; public Dictionary<int,ClientSocket> clientDic=new Dictionary<int,ClientSocket>();
private bool isClosed = false; public void Start(string ip,int prot,int num) { socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), prot); socket.Bind(ipPoint); socket.Listen(num); ThreadPool.QueueUserWorkItem(Accept); ThreadPool.QueueUserWorkItem(Receive);
} public void Close() { isClosed = true; foreach (var client in clientDic.Values) { client.Close(); } clientDic.Clear(); socket.Shutdown(SocketShutdown.Both); socket.Close(); } private void Accept(object obj) { while (!isClosed) { try { Socket clientSocket = socket.Accept(); ClientSocket client = new ClientSocket(clientSocket); clientDic.Add(client.clientId, client); client.Send("欢迎连入服务器"); } catch (Exception e) { Console.WriteLine("客户端连入报错"+e.Message); } } } private void Receive(object obj) { while (!isClosed) { if (clientDic.Count > 0) { foreach (ClientSocket client in clientDic.Values) { client.Receive(); } } } }
public void Broadcast(string info) { foreach (var client in clientDic.Values) { client.Send(info); } } }
|
2.客户端Socket
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public class ClientSocket { private static int CLIENT_START_ID = 1; public int clientId; public Socket socket; public ClientSocket(Socket socket) { this.socket = socket; this.clientId = CLIENT_START_ID; ++CLIENT_START_ID; } public bool Connected => socket.Connected; public void Close() { socket.Shutdown(SocketShutdown.Both); socket.Close(); } public void Send(string info) { try { socket.Send(Encoding.UTF8.GetBytes(info)); } catch (Exception e) { Console.WriteLine(e.Message); Close(); } } public void Receive() { try { if (socket.Available > 0) { byte[] result = new byte[1024*5]; int receiveNum = socket.Receive(result); ThreadPool.QueueUserWorkItem(MessageHandle,Encoding.UTF8.GetString(result, 0, receiveNum)); } } catch (Exception e) { Console.WriteLine(e.Message); Close(); } } private void MessageHandle(object obj) { string info = obj as string; Console.WriteLine("收到客户端{0}发来的消息:{1}", this.socket.RemoteEndPoint,info); } }
|
3.主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Program { static void Main(string[] args) { SeverSocket socket = new SeverSocket(); socket.Start("127.0.0.1",8080,10); Console.WriteLine("服务器开启成功"); while (true) { string input = Console.ReadLine(); if (input == "Quit") { socket.Close(); } else if(input.Substring(0,2) == "B:") { socket.Broadcast(input.Substring(2)); } } } }
|