棋牌游戏(炸金花)——服务器篇

操作步骤

  1. 创建一个类库(不创建控制台应用)
  2. 创建一个类(服务器类)(ServerPeer)
  3. 启动服务器
  4. 绑定Ip和端口号
  5. 接收客服端的连接
  6. 处理连接请求
  7. 创建一个类(客服端类)(ClientServer)
  8. 创建客服端连接池
  9. 填满客服端连接池
  10. 异步处理数据的接收

代码实现如下:
//服务器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// 服务器端
/// </summary>
namespace Card_MyServer
{
    public class ServerPeer
    {
        private Socket serverSocket;
        private Semaphore semaphore;//处理请求连接(控制线程)
        private ClentPeerPool clientPeerPool;
        private void StartServer(string ip, int port, int maxClient)
        {
            try
            {
                clientPeerPool = new ClentPeerPool(maxClient);
                semaphore = new Semaphore(maxClient, maxClient);
                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                for (int i = 0; i < maxClient; i++)//填满客服端连接池
                {
                    ClientPeer clientPeer = new ClientPeer();
                    clientPeer.ReceiveAsync.Completed += ReceiveAsync_Completed;
                    clientPeerPool.Enquere(clientPeer);
                }
                serverSocket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));//绑定IP和端口号
                serverSocket.Listen(maxClient);//开始监听 maxClient最大监听数
                Console.WriteLine("服务器启动成功!");
                //等待连接
                StartAccept(null);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        } 
        #region 客服端的连接
        /// <summary>
        /// 接收客服端的连接
        /// </summary>
        /// <param name="e">异步接收的套接字</param>
        private void StartAccept(SocketAsyncEventArgs e)
        {
            if (e == null)
            {
                e = new SocketAsyncEventArgs();
                e.Completed += E_Completed;
            }

            //result 为true 代表正在接收连接,连接成功触发 E_Completed方法
            //result 为false 代表连接成功
            bool result = serverSocket.AcceptAsync(e);
            if (result == false)//接收成功 调用处理连接的方法
            {
                ProcessAccept(e);
            }
        }
        /// <summary>
        /// 处理连接请求
        /// </summary>
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            semaphore.WaitOne();//控制线程(比如:两个跑步机只能有两个人,在来的只能等待有一个人走)
            ClientPeer client = clientPeerPool.Dequeue();
            client.clientSocket = e.AcceptSocket;
            Console.WriteLine(client.clientSocket.RemoteEndPoint + "客服端连接成功");
            //接收消息 
            StartReceive(client);
            //伪递归 循环接收连接
            e.AcceptSocket = null;
            StartAccept(e);

        }
        /// <summary>
        /// result为true的时候触发的方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void E_Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessAccept(e);
        }

        #endregion

        /// <summary>
        /// 开始接收数据
        /// </summary>
        /// <param name="client"></param>
        private void StartReceive(ClientPeer client)
        {
            try
            {
                bool result = client.clientSocket.ReceiveAsync(client.ReceiveAsync);
                if (result == false)
                {
                    ProcessReceive(client.ReceiveAsync);
                }
            }
            catch (Exception e)
            {

                Console.WriteLine(e.Message);
            }
           

        }

        /// <summary>
        /// 处理数据的接收
        /// </summary>
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            ClientPeer client = e.UserToken as ClientPeer;
            //判断数据是否接收成功
            if (client.ReceiveAsync.SocketError==SocketError.Success&&client.ReceiveAsync.BytesTransferred>0)
            {
                byte[] packet=new byte[client.ReceiveAsync.BytesTransferred];
                Buffer.BlockCopy(client.ReceiveAsync.Buffer,0,packet,0, client.ReceiveAsync.BytesTransferred);

                //让ClientPeer自身处理接收的数据
                client.ProcessReceive(packet);

                StartReceive(client);
            }
            else//断开连接
            {

            }
        }

        /// <summary>
        /// 异步接收数据完成后的操作
        /// </summary>
        private void ReceiveAsync_Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessReceive(e);
            
        }
    }
}

//客服端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Card_MyServer
{
    public class ClientPeer
    {
        public Socket clientSocket { get; set; }
        public SocketAsyncEventArgs ReceiveAsync { get; set; }//异步接收数据的套接字操作
        public ClientPeer()
        {
            ReceiveAsync = new SocketAsyncEventArgs();
            ReceiveAsync.UserToken = this;
            ReceiveAsync.SetBuffer(new byte[2048],0,2048);
        }
        /// <summary>
        /// 处理接收到的数据
        /// </summary>
        public void ProcessReceive(byte[] packet)
        {

        }
    }
}

//客服端连接池

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Card_MyServer
{
    public class ClentPeerPool
    {
        private Queue<ClientPeer> clientPeers;
        public ClentPeerPool(int maxCount)
        {
            clientPeers = new Queue<ClientPeer>(maxCount);
        }
        public void Enquere(ClientPeer client)
        {
            clientPeers.Enqueue(client);
           
        }
        public ClientPeer Dequeue()
        {
            return clientPeers.Dequeue();
        }
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值