Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

服务端实现示例

一、最基础的服务端实现

实现的基本步骤: 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
//1.创建套接字Socket
Socket socketTcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.使用Bind方法将套接字和本地地址绑定
try
{
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);
socketTcp.Bind(ipPoint);
}
catch (Exception e)
{
Console.WriteLine("绑定报错"+e.Message);
return;
}
//3.使用Listen监听
socketTcp.Listen(1024);
Console.WriteLine("服务端绑定监听结束,等待客户端连入");
//4.用Accept方法等待客户端链接
//5.建立链接,Accept返回新套接字
Socket socketClient = socketTcp.Accept();
//6.使用Send和Receive相关方法收发数据
//发送数据
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));

//7.使用Shutdown方法释放链接
socketClient.Shutdown(SocketShutdown.Both);
//8.关闭套接字
socketClient.Close();
#endregion

Console.WriteLine("按任意键推出");
Console.ReadKey();

二、服务多个客户端的基本实现

  1. 建立Socket 绑定 监听
  2. 等待客户端链接(主要实现服务多个客户端)
    实现方向:多线程
  3. 收发消息
  4. 关闭相关
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;
//用于存储连入客户端的Socket
static List<Socket> _clientSockets = new List<Socket>();

private static bool _isClosed = false;
public static void Main(string[] args)
{
//1.建立Socket 绑定 监听
_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);
//2.等待客户端链接(主要实现服务多个客户端)
//实现方向:多线程
Thread acceptThread = new Thread(AcccptClientConnection);
acceptThread.Start();
Console.WriteLine("等待客户端链接");
//3.收发消息
//收发需要分别处理
Thread receiveThread = new Thread(receiveMessage);
receiveThread.Start();
//4.关闭相关
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
{
//服务端的Socket
public Socket 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;
}
/// <summary>
/// 是否是链接状态
/// </summary>
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));
}
}
}
}

评论