【现代程序设计】【homework-05】
这次作业的运行效果图:
新建了20个客户端线程,服务器相应开了20个线程接收客户端数据,每一秒输出每一轮的结果
这次作业用c#完成
利用 Socket 类实现了局域网中的客户端和服务器之间的通信
主要设计思路:
对于服务器:
每连接到一个客户端,就新建一个线程用于监听该客户端过来的数据
每一轮新的游戏开始,服务器即向连接到的客户端发送开始游戏的标志
在1.2s内,处理所有接收到的数据,显示结果,并再次发起新的一轮游戏
对于客户端:
每个客户端有个线程来接受服务器的发送的数据
在连接阶段客户端主动向服务器注册
客户端并不主动向服务器发送数据,而是根据服务器发送过来的指令类型,选择是否向服务器发送数据
下面是服务器和客户端用于通信的函数
对于服务器
public static void sendmessage() 向客户端发送数据
private static void ListenClientConnect():开一个线程监听客户端发送的数据
private static void ReceiveMessage(object clientSocket:处理接受到的客户端数据
对于客户端:
public void SendClientMessage(string smessage):用于向服务器发送数据
public void connnectserver():初始阶段连接到服务器
public void ReceiveSMessage():开一个线程接收服务器发送的数据
下面是完整的代码(c#):
服务器:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Net.Sockets; 7 using System.Net; 8 using System.Threading; 9 10 namespace C1 11 { 12 13 14 class ClientData 15 { 16 public string Mname { get; set; } 17 public string Mcode { get; set; } 18 public double Mnum { get; set; } 19 public bool IsSendNum { get; set; } 20 public Socket client { get; set; } 21 } 22 23 class NumSeryer 24 { 25 26 public static DateTime StartTime =new DateTime(); 27 public static DateTime EndTime = new DateTime(); 28 29 public static List<ClientData> ClientList = new List<ClientData>(); 30 31 32 public static int Nround=40; 33 34 private static byte[] result = new byte[1024]; 35 private static int myProt = 8885; //端口 36 static Socket serverSocket; 37 public static int nsum; 38 static void Main(string[] args) 39 { 40 //服务器IP地址 41 IPAddress ip = IPAddress.Parse("192.168.12.169"); 42 serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 43 serverSocket.Bind(new IPEndPoint(ip, myProt)); //绑定IP地址:端口 44 serverSocket.Listen(50); 45 Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString()); 46 //通过Clientsoket发送数据 47 48 Thread myThread = new Thread(ListenClientConnect); 49 myThread.Start(); 50 Console.ReadLine(); 51 } 52 53 54 /// 监听客户端连接 55 56 /// 57 58 59 60 public static void sendstart() 61 { 62 63 for (int i = 0; i < Nround; i++) 64 { 65 sendmessage(); 66 Thread.Sleep(1200); 67 68 double sum = 0, ave, jiange = 1111111111; 69 int n = 0, pos = 0; 70 71 foreach (ClientData xx in ClientList) 72 { 73 if (xx.IsSendNum) 74 { 75 sum += xx.Mnum; 76 n++; 77 } 78 } 79 80 81 ave = sum / n * 0.618; 82 83 for (int j = 0; j < ClientList.Count; j++) 84 { 85 ClientData xx = ClientList[j]; 86 if (xx.IsSendNum && jiange > Math.Abs(xx.Mnum - ave)) 87 { 88 jiange = Math.Abs(xx.Mnum - ave); pos = j; 89 } 90 } 91 92 Console.WriteLine("第{0}轮结果", i); 93 Console.WriteLine("参与客户端数:{0},G-number:{1}", n, ave); 94 Console.WriteLine("获胜客户端名字:{0},数值:{1}", ClientList[pos].Mname, ClientList[pos].Mnum); 95 Console.WriteLine(); 96 } 97 } 98 99 public static void sendmessage() 100 { 101 foreach(ClientData xx in ClientList) 102 xx.client.Send(Encoding.ASCII.GetBytes("Start")); 103 } 104 105 106 107 private static void ListenClientConnect() 108 { 109 while (true) 110 { 111 nsum++; 112 113 114 StartTime = DateTime.Now; 115 116 Socket clientSocket=serverSocket.Accept(); 117 118 ClientData _client = new ClientData { client =clientSocket }; 119 120 ClientList.Add(_client); 121 122 Thread receiveThread = new Thread(ReceiveMessage); 123 receiveThread.Start(clientSocket); 124 125 if (nsum >= 20) 126 { 127 sendstart(); 128 // return; 129 } 130 131 132 } 133 } 134 135 /// <summary> 136 /// 接收消息 137 /// </summary> 138 /// <param name="clientSocket"></param> 139 private static void ReceiveMessage(object clientSocket) 140 { 141 Socket myClientSocket = (Socket)clientSocket; 142 143 144 while (true) 145 { 146 try 147 { 148 //通过clientSocket接收数据 149 int receiveNumber = myClientSocket.Receive(result); 150 151 string ss = Encoding.ASCII.GetString(result, 0, receiveNumber); 152 153 string[] s = ss.Trim().Split('+'); 154 155 156 double tnum = 0; 157 158 if (s[0] == "Regester") 159 { 160 string[] stemp = s[1].Trim().Split('-'); 161 int index = int.Parse(stemp[1]); 162 ClientList[index].Mname = s[1]; 163 ClientList[index].Mcode = s[2]; 164 continue; 165 } 166 167 168 169 string tname = s[0]; 170 tnum = int.Parse(s[1]); 171 int n = ClientList.FindIndex(x => x.Mname == s[0]); 172 173 174 ClientList[n].Mnum = tnum; 175 ClientList[n].IsSendNum = true; 176 } 177 catch (Exception ex) 178 { 179 Console.WriteLine(ex.Message); 180 myClientSocket.Shutdown(SocketShutdown.Both); 181 myClientSocket.Close(); 182 break; 183 } 184 } 185 } 186 } 187 }
客户端:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Net; 7 using System.Net.Sockets; 8 using System.Threading; 9 10 namespace C2 11 { 12 class client 13 { 14 public static string ToBeginGame = "Start"; 15 private static byte[] result = new byte[1024]; 16 public string sname { get; set; } 17 public string scode { get; set; } 18 19 IPAddress ip = IPAddress.Parse("192.168.12.169"); 20 Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 21 22 public void Sign_Receive() 23 { 24 Thread Client_thread = new Thread(new ThreadStart(ReceiveSMessage)); 25 Client_thread.Start(); 26 } 27 28 public void ReceiveSMessage() 29 { 30 31 //通过clientSocket接收数据 32 while (true) 33 { 34 35 int receiveLength = clientSocket.Receive(result); 36 37 string ss = Encoding.ASCII.GetString(result, 0, receiveLength); 38 39 if (ss == ToBeginGame) 40 { 41 SendNum(); 42 } 43 } 44 45 } 46 47 public void connnectserver() 48 { 49 try 50 { 51 clientSocket.Connect(new IPEndPoint(ip, 8885)); //配置服务器IP与端口 52 Console.WriteLine("连接服务器成功"); 53 } 54 catch 55 { 56 Console.WriteLine("连接服务器失败,请按回车键退出!"); 57 return; 58 } 59 } 60 61 public void Regester() 62 { 63 SendClientMessage("Regester"+"+"+sname + "+" + scode); 64 } 65 66 public void SignIn() 67 { 68 SendClientMessage(sname + "" + scode); 69 } 70 71 public void SendNum() 72 { 73 Random _random = new Random(); 74 75 76 Random r = new Random(); 77 78 byte[] buffer = Guid.NewGuid().ToByteArray(); 79 int iSeed = BitConverter.ToInt32(buffer, 0); 80 r = new Random(iSeed); 81 int x; 82 x = r.Next(1000); 83 84 85 86 SendClientMessage(sname+"+"+x.ToString()); 87 } 88 89 public void SendClientMessage(string smessage) 90 { 91 try 92 { 93 clientSocket.Send(Encoding.ASCII.GetBytes(smessage)); 94 } 95 catch 96 { 97 clientSocket.Shutdown(SocketShutdown.Both); 98 clientSocket.Close(); 99 } 100 } 101 102 103 } 104 }
一个控制台程序,用于生成20个客户端:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Net; 7 using System.Net.Sockets; 8 using System.Threading; 9 10 namespace C2 11 { 12 13 14 class saaaa 15 { 16 public static void Main() 17 { 18 19 20 client[] a =new client[20]; 21 for (int i = 0; i < 20; i++) 22 { 23 a[i] = new client { sname = "c-" + i.ToString(), scode = "123" }; 24 a[i].connnectserver(); 25 a[i].Sign_Receive(); 26 a[i].Regester(); 27 } 28 29 Console.ReadLine(); 30 } 31 } 32 }