视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001 知道1 知道21 知道41 知道61 知道81 知道101 知道121 知道141 知道161 知道181 知道201 知道221 知道241 知道261 知道281
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
C#利用服务器实现客户端之间通信
2020-11-27 22:36:36 责编:小采
文档

先来讲述下我自己对于整个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端代码 

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端代码(因为都差不多 就只贴一个了) 

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[]数组的大小而不是内容的大小。 

这个大家就自己尝试吧。

下载本文
显示全文
专题