C#利用服务器实现客户端之间通信

时间:2022-03-22 12:18:08

先来讲述下我自己对于整个Socket通信过程的理解,毕竟初学,说错见谅,知道错了会改正~ 

首先在服务端新建一个serverSocket,对其进行初始化(一般包含AddressFamily:IP地址类型,SocketType:Socket传输数据方式,ProtoType:传输协议); 

接着我们要设置server端要绑定的IP:port;然后开始监听,并设置最多同时监听多少个Client.

这时,服务端就在等待状态,直到某一个Client连接到这个ip:port上,这时serverSocket.Accept()工作,获得这个连接。(此时的连接是有地址信息的哦!记得保存) 

获得连接之后,server就可以和这个Client进行通信了,当加入第二个Client(我们称其为ClientB)时,Server接收到ClientB的消息,可以将这个消息转发给前一个Client(我们称其为ClientA),当受到ClientA的消息,也可以转发给ClientB。这样就实现了Clients之间的通信了。(重点在保存连接信息!!)

那么现在贴上代码讲解:

Server端代码 

 

?
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
namespace SocketServer
{
  class Program
  {
    private static byte[] result = new byte[1024];
   
    static Socket serverSocket;
    private static string client;
    private static Socket clientSocket;
    //我这里存了两个Client,因为自己电脑开了两个Client,不会有多的
    //理论上应该开一个Socket[]来保存信息,最好用一个二元组将client的信息和连接绑定起来
    //这样就可以实现断开连接后下次登陆还是可以识别是这个Client
    private static Socket clientSocketA=null;
    private static Socket clientSocketB=null;
    
    static void Main(string[] args)
    {
      Program.SetPort(8885);
    }
    private static void SetPort(int port)
    {
      IPAddress ip = IPAddress.Parse("127.0.0.1");//set ip
      serverSocket = new Socket(AddressFamily.InterNetwork,
        SocketType.Stream, ProtocolType.Tcp);//initialize
      serverSocket.Bind(new IPEndPoint(ip, port));//bind
      serverSocket.Listen(10);
      //进入监听状态
      Console.WriteLine("监听{0}成功", serverSocket.LocalEndPoint.ToString());
      //开启一个线程来监听客户端连接
      Thread myThread = new Thread(ListenClientConnect);
      myThread.Start();
      Console.ReadLine();
 
    }
    /// <summary>
    /// 监听客户端连接
    /// </summary>
    private static void ListenClientConnect()
    {
      while (true)
      {
        //Client连接上后 得到这个连接
        clientSocket = serverSocket.Accept();
 
        //这里我因为只有两个Client,所以就简单写了
        if (clientSocketA == null)
        {
          clientSocketA = clientSocket;
        }
        else if (clientSocketB == null)
        {
          clientSocketB = clientSocket;
        }
        else
        {
          //当其中一个断开了,又重新连接时,需要再次保存连接
          if (clientSocketB.IsBound)
          {
            clientSocketA = clientSocketB;
            clientSocketB = clientSocket;
          }
          else
          {
            clientSocketB = clientSocketA;
            clientSocketA = clientSocket;
          }
          
        }
        clientSocket.Send(Encoding.ASCII.GetBytes("say hello"));
        //开个线程接收Client信息
        Thread receivedThread = new Thread(ReceiveMessage);
        receivedThread.Start(clientSocket);
 
      }
    }
   
    private static void ReceiveMessage(object clientSocket)
    {
      Socket myClientSocket = (Socket) clientSocket;
      
      while (true)
      {
        try
        {
          int revceiveNumber = myClientSocket.Receive(result);
          //Console.WriteLine("接受客户端{0}消息{1}", myClientSocket.RemoteEndPoint.ToString()
          //  , Encoding.ASCII.GetString(result, 0, revceiveNumber));
          Console.WriteLine(Encoding.ASCII.GetString(result, 0, revceiveNumber));
          if (myClientSocket == clientSocketA)
          {
            Console.WriteLine("receive from A");
            if (clientSocketB!=null&&clientSocketB.IsBound)
            {
              Console.WriteLine("a IS BOUND");
              clientSocketB.Send(result, 0, revceiveNumber, SocketFlags.None);
            }
            else
            {
              myClientSocket.Send(Encoding.ASCII.GetBytes("the people is not online! Send Failed!"));
              Console.WriteLine("对方不在线上,发送失败!");
            }
          }
          else
          {
            Console.WriteLine("receive from B");
            if (clientSocketA != null && clientSocketA.IsBound)
            {
              Console.WriteLine("a IS BOUND");
              clientSocketA.Send(result, 0, revceiveNumber, SocketFlags.None);
            
            else
            {
              myClientSocket.Send(Encoding.ASCII.GetBytes("the people is not online! Send Failed!"));
              Console.WriteLine("对方不在线上,发送失败!");
            }
 
          }
          
        }
        catch(Exception ex)
        {
          Console.WriteLine(ex.Message);
          myClientSocket.Shutdown(SocketShutdown.Both);
          myClientSocket.Close();
          break;
 
        }
      }
 
    }
  }
}

Client端代码(因为都差不多 就只贴一个了) 

 

?
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
namespace SocketClient
{
  class Program
  {
    private static byte[] result = new byte[1024];
    private static Socket clientSocket;
    private static void ListenServer()
    {
      while (true)
      {
        result = new byte[1024];
        int receiveLength = clientSocket.Receive(result);
        
        Console.WriteLine("{0}", Encoding.ASCII.GetString(result, 0, receiveLength));
      }
      
    }
    static void Main(string[] args)
    {
 
      IPAddress ip = IPAddress.Parse("127.0.0.1");
      clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      try
      {
        clientSocket.Connect(ip, 8885);
        Console.WriteLine("连接成功!");
 
      }
      catch (Exception e)
      {
        Console.WriteLine("连接失败!");
        return;
      }
      Thread threadRead = new Thread(ListenServer);
      threadRead.Start();
     
 
      while(true)
      {
        try
        {
          Thread.Sleep(1000);
          string sendMessage = Console.ReadLine();
          clientSocket.Send(Encoding.ASCII.GetBytes("Sylvia:"+sendMessage));
          
        }
        catch (Exception ex)
        {
          clientSocket.Shutdown(SocketShutdown.Both);
          clientSocket.Close();
          break;
        }
 
      }
      Console.WriteLine("发送完毕 按回车退出");
      Console.ReadKey();
    }
  }
}

写的时候要特别注意一下Send信息的时候,注意byte[]的传输大小,很容易变成byte[]数组的大小而不是内容的大小。 

这个大家就自己尝试吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。