首先非常抱歉第三次和第四次作业我没交上来,不想找借口强调原因,但是这两次作业我一定会补上,到时候会@助教。谢谢
回到这次作业!
这次作业邹老师没说博客的格式,所以在这里就没有什么回答问题的东西了。这次由于是自由组队我觉得猪脚应该没有我们的名单,所以在这里附上,如下
11061014 王冠乔
11061027 张盛兴
11061008 谢子鸣
这次作业主要是做一个服务器与客户端的连接,其中黄金点的算法思想应该是在下一周里面提交,所以在这里面就不说算法了,既然只是简单的建立一个小协议和简单的服务器客户端程序,就没必要大费周章,我是用c#的socket类来简单写的通信,而处理也比较简单。
客户端代码如下:
class client { public static string ToBeginGame = "Start"; private static byte[] result = new byte[1024]; public string sname { get; set; } public string scode { get; set; } IPAddress ip = IPAddress.Parse("192.168.137.1"); Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); public void Sign_Receive() { Thread Client_thread = new Thread(new ThreadStart(ReceiveSMessage)); Client_thread.Start(); } public void ReceiveSMessage() { //通过clientSocket接收数据 while (true) { int receiveLength = clientSocket.Receive(result); string ss = Encoding.ASCII.GetString(result, 0, receiveLength); if (ss == ToBeginGame) { SendNum(); } } } public void connnectserver() { try { clientSocket.Connect(new IPEndPoint(ip, 8885)); //配置服务器IP与端口 Console.WriteLine("连接服务器成功"); } catch { Console.WriteLine("连接服务器失败,请按回车键退出!"); return; } } public void Regester() { SendClientMessage("Regester"+"+"+sname + "+" + scode); } public void SignIn() { SendClientMessage(sname + "" + scode); } public void SendNum() { Random _random = new Random(); Random r = new Random(); byte[] buffer = Guid.NewGuid().ToByteArray(); int iSeed = BitConverter.ToInt32(buffer, 0); r = new Random(iSeed); int x; x = r.Next(1000); SendClientMessage(sname+"+"+x.ToString()); } public void SendClientMessage(string smessage) { try { clientSocket.Send(Encoding.ASCII.GetBytes(smessage)); } catch { clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); } } }
主函数如下:
public static void Main() { client[] a = new client[20]; for (int i = 0; i < 20; i++) { a[i] = new client { sname = "c-" + i.ToString(), scode = "123" }; a[i].connnectserver(); a[i].Sign_Receive(); a[i].Regester(); } Console.ReadLine(); }
服务器代码如下:
class ClientData { public string Mname { get; set; } public string Mcode { get; set; } public double Mnum { get; set; } public bool IsSendNum { get; set; } public Socket client { get; set; } } class NumSeryer { public static DateTime StartTime = new DateTime(); public static DateTime EndTime = new DateTime(); public static List<ClientData> ClientList = new List<ClientData>(); public static int Nround = 40; private static byte[] result = new byte[1024]; private static int myProt = 8885; //端口 static Socket serverSocket; public static int nsum; static void Main(string[] args) { //服务器IP地址 IPAddress ip = IPAddress.Parse("127.0.0.1"); serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSocket.Bind(new IPEndPoint(ip, myProt)); //绑定IP地址:端口 serverSocket.Listen(50); Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString()); //通过Clientsoket发送数据 Thread myThread = new Thread(ListenClientConnect); myThread.Start(); Console.ReadLine(); } /// 监听客户端连接 /// public static void sendstart() { for (int i = 0; i < Nround; i++) { sendmessage(); Thread.Sleep(1200); double sum = 0, ave, jiange = 1111111111; int n = 0, pos = 0; foreach (ClientData xx in ClientList) { if (xx.IsSendNum) { sum += xx.Mnum; n++; } } ave = sum / n * 0.618; for (int j = 0; j < ClientList.Count; j++) { ClientData xx = ClientList[j]; if (xx.IsSendNum && jiange > Math.Abs(xx.Mnum - ave)) { jiange = Math.Abs(xx.Mnum - ave); pos = j; } } Console.WriteLine("第{0}轮结果", i); Console.WriteLine("参与客户端数:{0},G-number:{1}", n, ave); Console.WriteLine("获胜客户端名字:{0},数值:{1}", ClientList[pos].Mname, ClientList[pos].Mnum); Console.WriteLine(); } } public static void sendmessage() { foreach (ClientData xx in ClientList) xx.client.Send(Encoding.ASCII.GetBytes("Start")); } private static void ListenClientConnect() { while (true) { nsum++; StartTime = DateTime.Now; Socket clientSocket = serverSocket.Accept(); ClientData _client = new ClientData { client = clientSocket }; ClientList.Add(_client); Thread receiveThread = new Thread(ReceiveMessage); receiveThread.Start(clientSocket); if (nsum >= 20) { sendstart(); // return; } } } /// <summary> /// 接收消息 /// </summary> /// <param name="clientSocket"></param> /// private static void ReceiveMessage(object clientSocket) { Socket myClientSocket = (Socket)clientSocket; while (true) { try { //通过clientSocket接收数据 int receiveNumber = myClientSocket.Receive(result); string ss = Encoding.ASCII.GetString(result, 0, receiveNumber); string[] s = ss.Trim().Split('+'); double tnum = 0; if (s[0] == "Regester") { string[] stemp = s[1].Trim().Split('-'); int index = int.Parse(stemp[1]); ClientList[index].Mname = s[1]; ClientList[index].Mcode = s[2]; continue; } string tname = s[0]; tnum = int.Parse(s[1]); int n = ClientList.FindIndex(x => x.Mname == s[0]); ClientList[n].Mnum = tnum; ClientList[n].IsSendNum = true; } catch (Exception ex) { Console.WriteLine(ex.Message); myClientSocket.Shutdown(SocketShutdown.Both); myClientSocket.Close(); break; } } } }
程序的大体框架就是首先服务器通过ListenClientConnect函数来一直监听客户端传来的消息,通过serverSocket.Accept得到socket类,服务器创建了一个客户端list来储存收到的注册的客户端,而没接受一个客户端泽新建一个线程来执行ReceiveMessage函数,ReceiveMessage负责接受注册的信息包括客户端的账号和密码,这里我们吧所有的信息(包括注册的信息和发送的有理数)都一起发送过来,只不过注册的信息开头会有一个Regester来区分,服务器统计我收的客户端数量囚达到20个就开始发送开始游戏命令到每个注册用户中,这时候另一台机(客户端)会建立20个线程(注册用户)来等待开始游戏命令,一旦接受送回一个随机数,每一轮锦标赛服务器都会统计一下在规定的1.2秒内(从发送开始游戏命令开始算起)的参与客户端数量,并算出优胜者,输出当前锦标赛轮数,参与的用户数量,黄金点的值和优胜用户的名字和对应的值;
进行规定论述的锦标赛,输出最佳的人;