猜数字游戏server端的代码,求高手解释

software 发布于 2013/09/05 15:05
阅读 156
收藏 0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.Net;
//使用Tcp协议
namespace AsyncTcpServer
{
    public partial class FormServer : Form
    {
        private bool isExit = false;
        //保存连接的所有客户端
        System.Collections.ArrayList clientList = new System.Collections.ArrayList();
        System.Collections.ArrayList clientClassList = new System.Collections.ArrayList();
        TcpListener listener;
        //创建托管,为了让窗口中的数据进行更新
        private delegate void SetListBoxCallback(string str);//定义托管
        private SetListBoxCallback setListBoxCallback;//声明对象

        private delegate void SetRichTextBoxCallback(string str);//托管
        private SetRichTextBoxCallback setRichTextBoxCallback;

        private delegate void SetComboBoxCallback(string str);//托管
        private SetComboBoxCallback setComboBoxCallback;

        private delegate void RemoveComboBoxItemsCallback(ReadWriteObject readWriteObject);//托管
        private RemoveComboBoxItemsCallback removeComboBoxItemsCallback;

        private delegate void HandleMessage(string str);//托管
        private HandleMessage handleMessage;

        //用于线程同步,初始状态设为非终止状态,使用手动重置方式
        private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);
        //初始化 EventWaitHandle 类的新实例,并指定等待句柄最初是否处于终止状态,以及它是自动重置还是手动重置。
        public FormServer()
        {
            InitializeComponent();//初始化
            listBoxStatus.HorizontalScrollbar = true;
            setListBoxCallback = new SetListBoxCallback(SetListBox);//将方法注册到委托实例中
            setRichTextBoxCallback = new SetRichTextBoxCallback(SetReceiveText);
            setComboBoxCallback = new SetComboBoxCallback(SetComboBox);
            handleMessage = new HandleMessage(ControlMessage);
            removeComboBoxItemsCallback = new RemoveComboBoxItemsCallback(RemoveComboBoxItems);
        }

        //设置列表
        private void SetListBox(string str) 
        {
            listBoxStatus.Items.Add(str);//数据传输,后台向前台传输数据
        }
        //在richTextBoxReceive中显示接收的内容
        private void SetReceiveText(string str) 
        {
            richTextBoxReceive.AppendText(str);
        }

        private void SetComboBox(string str)
        {
            userList.Items.Clear();
            foreach (ClientClass obj in clientClassList)
            {
                string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                string tempInfo;
                //判断用户是否在游戏中
                if (obj.flag)
                {
                    tempInfo = tempIP + ":" + tempPort.ToString() + "游戏中";
                }
                else 
                {
                    tempInfo = tempIP + ":" + tempPort.ToString();
                }

                userList.Items.Add(tempInfo);
                userList.SelectedIndex = userList.Items.Count - 1;//列表指针下移
                userList.ClearSelected();
            }
        }

        //开始监听
        private void buttonStart_Click(object sender, EventArgs e)
        {
            ThreadStart s = new ThreadStart(AcceptConnect);//创建线程
            Thread myThread = new Thread(s);
            myThread.IsBackground = true;//关掉窗口就可以关掉线程
            myThread.Start();//开始线程
            buttonStart.Enabled = false;//防止按钮多次点击
            //buttonStop.Enabled = true;
        }

        private void AcceptConnect() 
        {
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            listener = new TcpListener(ip, 51888);//设置端口
            listener.Start();//开始监听
            listBoxStatus.Invoke(setListBoxCallback, "等待客户端连接...");
            while (isExit == false) 
            {
                try
                {
                    //将事件的状态设置为非终止
                    allDone.Reset();
                    //引用在异步操作完成时调用的回调方法
                    AsyncCallback callback = new AsyncCallback(AcceptTcpClientCallback);
                    
                    //开始一个异步操作接受传入的连接尝试
                    listener.BeginAcceptTcpClient(callback, listener);
                    //阻塞当前线程,直到收到客户连接信号
                    allDone.WaitOne();
                }
                catch (Exception err) 
                {
                    //listBoxStatus.Invoke(setListBoxCallback, "1"+err.Message);
                    break;
                }
            }        
        }

        private void AcceptTcpClientCallback(IAsyncResult ar) 
        {
            try
            {
                //将事件状态设置为终止状态,允许一个或多个等待线程继续
                allDone.Set();
                TcpListener myListener = ar.AsyncState as TcpListener;
                TcpClient client = myListener.EndAcceptTcpClient(ar);//异步接收
                listBoxStatus.Invoke(setListBoxCallback, "接受客户端连接:" + client.Client.RemoteEndPoint);//在listBoxStatus中显示

                ReadWriteObject readWriteObject = new ReadWriteObject(client);//读取数据
                //clientList.Add(readWriteObject);
                ClientClass tempClient = new ClientClass(readWriteObject);//保存在ClientClass中
                clientClassList.Add(tempClient);

                userList.Invoke(setComboBoxCallback, client.Client.RemoteEndPoint.ToString());//在userList中显示
                SendMessage(readWriteObject, "服务端已经接受连接");
                SendClientList();//向客户端发送列表

                readWriteObject.netStream.BeginRead(readWriteObject.readBytes,
                    0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject);//异步读取,调用ReadCallback
                //测试
                readWriteObject.netStream.Flush();//刷新流中的数据
                
            }
            catch (Exception err) 
            {
                //listBoxStatus.Invoke(setListBoxCallback, "2" + err.Message);
                return;
            }
        }

        private void ReadCallback(IAsyncResult ar) //接收传过来的消息
        {
            try 
            {
                ReadWriteObject readWriteObject = ar.AsyncState as ReadWriteObject;
                int count = readWriteObject.netStream.EndRead(ar);

                richTextBoxReceive.Invoke(handleMessage, string.Format(System.Text.Encoding.UTF8.GetString(readWriteObject.readBytes, 0, count)));

                if (isExit == false) 
                {
                    readWriteObject.InitReadArray();
                    readWriteObject.netStream.BeginRead(readWriteObject.readBytes,
                        0, readWriteObject.readBytes.Length, ReadCallback, readWriteObject);
                    
                    readWriteObject.netStream.Flush();
                }

            }
            catch (Exception err)
            {
                //listBoxStatus.Invoke(setListBoxCallback, "3" + err.Message);
                SetComboBox("");
            }
        }
        //将信息发送出去
        private void SendString(ReadWriteObject readWriteObject, string str)
        {
            try 
            {
                readWriteObject.writeBytes = System.Text.Encoding.UTF8.GetBytes(str + "\r\n");
                readWriteObject.netStream.BeginWrite(readWriteObject.writeBytes,
                    0, readWriteObject.writeBytes.Length, new AsyncCallback(SendCallback), readWriteObject);
                readWriteObject.netStream.Flush();
                richTextBoxReceive.Invoke(setRichTextBoxCallback, string.Format("[发送{0}]{1}\r\n",
                    readWriteObject.client.Client.RemoteEndPoint, str.Substring(str.LastIndexOf('&')+1)));

            }
            catch (Exception err)
            {
                //listBoxStatus.Invoke(setListBoxCallback, "4" + err.Message);
            }
        }

        private void SendCallback(IAsyncResult ar) 
        {
            ReadWriteObject readWriteObject = ar.AsyncState as ReadWriteObject;
            try 
            {
                readWriteObject.netStream.EndWrite(ar);
            }
            catch (Exception err)
            {
                //listBoxStatus.Invoke(setListBoxCallback, "5" + err.Message);
                //userList.Invoke(removeComboBoxItemsCallback, readWriteObject);
            }
        }

        private void RemoveComboBoxItems(ReadWriteObject readWriteObject)
        {
            int index = clientList.IndexOf(readWriteObject);
            userList.Items.RemoveAt(index);
        }
        //发送列表
        private void SendClientList()
        {
            //生成客户端列表
            string temp_list = "";
            foreach (ClientClass obj in clientClassList)
            {
                if (obj.flag)
                {
                    temp_list += "游戏中:0|";
                }
                else
                {
                    temp_list += obj.clientObject.client.Client.RemoteEndPoint.ToString() + '|';
                }
            }
            temp_list = temp_list.Substring(0, temp_list.Length - 1);
            //向所有的客户端发送列表
            foreach (ClientClass obj in clientClassList)
            {
                SendMessage(obj.clientObject, temp_list, 8);
            }
        }
        //将退出游戏的玩家移除
        private void RemoveClientFromUserList(string ip, int port)
        {
            foreach (ClientClass obj in clientClassList)
            {
                string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                if (tempIP == ip && tempPort == port)
                {
                    clientClassList.Remove(obj);
                    return;
                }
            }
            SetComboBox("");
        }

        //分类接收数据,进行处理
        private void ControlMessage(string str)
        {
            Message toReceive = new Message(str);

            //调试使用
            //SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString() + "]" + str + "\r\n");

            switch (toReceive.Type)
            {
                //0:发送消息给服务器(默认值,测试用)
                case 0:
                    break;
                //1:发送用户名
                case 1:
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.oriIP && tempPort == toReceive.oriPort)
                        {
                            obj.setClientName(toReceive.Content);
                            break;
                        }
                    }
                    break;
                //2:请求与对手建立连接
                case 2:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]请求与" + toReceive.desIP + ":" + toReceive.desPort.ToString() + "游戏\r\n");
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            SendMessage(obj.clientObject, toReceive.oriIP, toReceive.oriPort, "2", 2);
                        }
                    }
                    break;
                //4:发送给对手游戏数据
                case 4:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]发送数据:" + toReceive.Content + "\r\n");
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.oriIP && tempPort == toReceive.oriPort)
                        {
                            obj.setSelfNumber(toReceive.Content);
                            break;
                        }
                    }
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            obj.setOpponentNumber(toReceive.Content);
                            SendMessage(obj.clientObject, toReceive.Content, 4);
                            break;
                        }
                    }
                    break;
                //5:请求开牌
                case 5:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]请求开牌\r\n");
                    int result = 0;
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.oriIP && tempPort == toReceive.oriPort)
                        {
                            result = obj.getWinner();
                            if (result == 1)
                            {
                                SendMessage(obj.clientObject, "1", 11);
                            }
                            else if (result == 2)
                            {
                                SendMessage(obj.clientObject, "0", 11);
                            }
                            else
                            {
                                SendMessage(obj.clientObject, "2", 11);
                            }
                            obj.gameNumberFlag = false;
                            break;
                        }
                    }
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            if (result == 2)
                            {
                                SendMessage(obj.clientObject, "1", 11);
                            }
                            else if (result == 1)
                            {
                                SendMessage(obj.clientObject, "0", 11);
                            }
                            else
                            {
                                SendMessage(obj.clientObject, "2", 11);
                            }
                            obj.gameNumberFlag = false;
                            break;
                        }
                    }
                    break;
                //6:聊天内容
                case 6:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]聊天内容:" + toReceive.Content + "\r\n");
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            SendMessage(obj.clientObject, toReceive.Content, 6);
                        }
                    }
                    break;
                //7:断开连接
                case 7:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]客户端" + toReceive.oriIP + ":" + toReceive.oriPort.ToString() + "断开连接\r\n");
                    RemoveClientFromUserList(toReceive.oriIP, toReceive.oriPort);
                    //foreach (ClientClass obj in clientClassList)
                    //{
                    //    string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                    //    string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                    //    int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                    //    if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                    //    {
                    //        if (obj.flag)
                    //        {
                    //            SendMessage(obj.clientObject,"16",16);
                    //            break;
                    //        }
                    //    }
                    //}
                    SendClientList();
                    break;
                //8:请求更新客户列表
                case 8:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]更新客户列表\r\n");
                    SendClientList();
                    break;
                //9:发送给服务器自己色子情况
                case 9:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]骰子:" + toReceive.Content + "\r\n");
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.oriIP && tempPort == toReceive.oriPort)
                        {
                            obj.setGameNumber(toReceive.Content);
                            if (obj.gameNumberFlag)
                            {
                                SendMessage(obj.clientObject, toReceive.desIP, toReceive.desPort, "12", 12);
                            }
                            break;
                        }
                    }
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            obj.setGameNumber(toReceive.Content);
                            if (obj.gameNumberFlag)
                            {
                                SendMessage(obj.clientObject, toReceive.oriIP, toReceive.desPort, "12", 12);
                            }
                            break;
                        }
                    }
                    break;
                //10:同意与玩家游戏
                case 10:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]同意与" + toReceive.desIP + ":" + toReceive.desPort.ToString() + "游戏\r\n");
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.oriIP && tempPort == toReceive.oriPort)
                        {
                            obj.setOpponentInfo(toReceive.desIP, toReceive.desPort);
                            obj.startGame();
                            break;
                        }
                    }
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            obj.setOpponentInfo(toReceive.oriIP, toReceive.oriPort);
                            obj.startGame();
                            SendMessage(obj.clientObject, toReceive.oriIP, toReceive.oriPort, "10", 10);
                            break;
                        }
                    }
                    SetComboBox("");
                    SendClientList();
                    break;
                //13:重开游戏
                case 13:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]请求重开游戏\r\n");
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.oriIP && tempPort == toReceive.oriPort)
                        {
                            obj.setResetTimes();
                            if (obj.resetFlag)
                            {
                                obj.resetGame();
                                SendMessage(obj.clientObject,"15",15);
                            }
                            break;
                        }
                    }
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            obj.setResetTimes();
                            if (!obj.resetFlag)
                            {
                                SendMessage(obj.clientObject, toReceive.oriIP, toReceive.oriPort, "13", 13);
                            }
                            if (obj.resetFlag)
                            {
                                obj.resetGame();
                                SendMessage(obj.clientObject, "15", 15);
                            }
                            break;
                        }
                    }
                    break;
                //14:重选对手
                case 14:
                    SetReceiveText("[接收" + toReceive.oriIP + ":" + toReceive.oriPort.ToString()
                        + "]重选对手\r\n");
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.oriIP && tempPort == toReceive.oriPort)
                        {
                            obj.resetOpponent();
                            break;
                        }
                    }
                    foreach (ClientClass obj in clientClassList)
                    {
                        string tempUser = obj.clientObject.client.Client.RemoteEndPoint.ToString();
                        string tempIP = tempUser.Substring(0, tempUser.IndexOf(':'));
                        int tempPort = int.Parse(tempUser.Substring(tempUser.IndexOf(':') + 1));

                        if (tempIP == toReceive.desIP && tempPort == toReceive.desPort)
                        {
                            SendMessage(obj.clientObject, toReceive.oriIP, toReceive.oriPort, "16", 16);
                            obj.resetOpponent();
                            break;
                        }
                    }
                    break;
                //15.双方都选择重开游戏
                //case 15:
                //    break;
                //16.收到对方说重选对手
                default:
                    break;
            }
        }

        //对消息进行封装
        //格式:发送段IP&发送端Port&接收端IP&接收端Port&消息类型&消息内容
        private void SendMessage(ReadWriteObject readWriteObject, string str, int type = 0)
        {
            string temp_info = readWriteObject.client.Client.RemoteEndPoint.ToString();
            string self_info = listener.LocalEndpoint.ToString();
            Message toSend = new Message(self_info.Substring(0, self_info.IndexOf(':')),
                int.Parse(self_info.Substring(self_info.IndexOf(':') + 1)),
                temp_info.Substring(0, temp_info.IndexOf(':')),
                int.Parse(temp_info.Substring(temp_info.IndexOf(':') + 1)),
                type, str);

            SendString(readWriteObject, toSend.convertToStream());
        }

        //转发SendMessage函数
        //重载
        private void SendMessage(ReadWriteObject readWriteObject, string oriIP, int oriPort, string str, int type = 0)
        {
            string temp_info = readWriteObject.client.Client.RemoteEndPoint.ToString();
            Message toSend = new Message(oriIP, oriPort,
                temp_info.Substring(0, temp_info.IndexOf(':')),
                int.Parse(temp_info.Substring(temp_info.IndexOf(':') + 1)),
                type, str);

            SendString(readWriteObject, toSend.convertToStream());
        }
        //停止sever
        private void buttonStop_Click(object sender, EventArgs e)
        {
            //使线程自动结束
            allDone.Set();
            buttonStart.Enabled = true;
            buttonStop.Enabled = false;

            isExit = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int index = userList.SelectedIndex;
            if (index == -1)
            {
                MessageBox.Show("请先选择接收方,然后再单击[发送]");
            }
            else 
            {
                ClientClass obj = clientClassList[index] as ClientClass;
                //ReadWriteObject objj = clientClassList[index] as ReadWriteObject;

                SendMessage(obj.clientObject, richTextSend.Text);
                richTextSend.Clear();
            }
        }

        private void FormServer_FormClosing(object sender, FormClosingEventArgs e)
        {
            buttonStop_Click(null, null);
        }

        private void FormServer_Load(object sender, EventArgs e)
        {

        }

    }
}
加载中
返回顶部
顶部