客户端-服务器拍卖系统.控制台模式

本文关键字:控制台 模式 系统 拍卖 服务器 客户端 | 更新日期: 2023-09-27 18:16:02

我使用c# Sockets。我正在做一个拍卖服务器和客户项目。控制台模式。实际上,我有一个服务器异步运行多个客户端。

主要问题:当1拍卖结束时,服务器必须发送消息给赢家(如果存在),卖家和输家。我需要一种时钟来触发事件。

在客户端,我可以发送如下命令:

  • "注册用户名密码"
  • "登录用户名密码"
  • "信用xxx.xx"
  • "创建产品min_price duration"—创建1个拍卖
  • 等。

现在我对拍卖系统的逻辑有点困惑。

当服务器读取(命令== " create ")时,它必须创建具有各自信息的拍卖。如何做到这一点?每次拍卖1条线?

当时间结束时,服务器必须回复:

  • 中标人(产品名称、中标金额)
  • 失败者(产品名称、最后一次出价、中标者出价)
  • 创建者(如果他的产品已售出)

我想过:

  1. 服务器读取命令" create "
  2. 服务器为拍卖创建一个新线程
  3. 线程有一个计时器,可以看到(线程)。定时器== time_to_end)?
  4. 当线程。定时器= time_to_end)发送所有消息!

这个伪代码可以执行吗?

我必须使用哪些类?

服务器代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using Server;
using System.IO;
namespace Server
{
    class Program
    {
        private static TcpClient _cashierClient = new TcpClient();
        private static Dictionary<string, User> loggedUsers = new Dictionary<string, User>(); // <username, User>
        private static Dictionary<string, int> loggedUsers2 = new Dictionary<string, int>(); // <IPEndPoint, ID>
        private static List<User> registeredUsers = new List<User>();
        private static byte[] _buffer = new byte[1024];
        private static List<Socket> _clientSockets = new List<Socket>();
        private static Socket _serverSocket = new Socket
            (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        static void Main(string[] args)
        {
            Console.Title = "Server";
            ConnectToCashier();
            SetupServer();
            Console.ReadLine();
        }
        private static void ConnectToCashier()
        {
            Console.WriteLine("Connecting to Cashier...");
            _cashierClient.Connect(IPAddress.Loopback, 101);
            Stream stream = _cashierClient.GetStream();
            byte[] receivedBuf = new byte[1024];
            int rec = stream.Read(receivedBuf, 0, 1024);
            byte[] data = new byte[rec];
            Array.Copy(receivedBuf, data, rec);
            Console.WriteLine(Encoding.ASCII.GetString(data));
        }
        private static void SetupServer()
        {
            Console.WriteLine("Setting up server...");
            _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100)); //Bind any interfaces on port 100
            _serverSocket.Listen(5); // Max 5 em Lista de espera
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
        }
        private static void AcceptCallback(IAsyncResult AR)
        {
            Socket socket = _serverSocket.EndAccept(AR);
            _clientSockets.Add(socket);
            Console.WriteLine("Client " + socket.RemoteEndPoint.ToString() + " connected");
            socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
        }
        private static void ReceiveCallBack(IAsyncResult AR)
        {
            Socket socket = (Socket)AR.AsyncState;
            int received = socket.EndReceive(AR);
            byte[] dataBuf = new byte[received];
            Array.Copy(_buffer, dataBuf, received);
            string text = Encoding.ASCII.GetString(dataBuf);
            Console.WriteLine(socket.RemoteEndPoint.ToString() + " sent: " + text);
            string response = string.Empty;
            string command = text.ToLower().Split()[0]; // "command word1 word2 word... wordX wordX+1"
            int words = text.Split().Count(); // count the number of words + command
            if (command == "get_time" && words == 1) // SERVER TIME
            {
                response = DateTime.Now.ToLongTimeString();
            }
            else if (command == "register" && words == 3) // REGIST USER
            {
                string[] split = text.Split();
                if (userExists(split[1]))
                {
                    response = "'" + split[1] + "' already in use. Choose another username";
                }
                else
                {
                    newUser(split[1], split[2]); //split[1] = name, split[2] = password
                    response = "'" + split[1] + "' Successfully Registered";
                }
            }
            else if (command == "login" && words == 3) // LOG IN
            {
                string[] split = text.Split();
                if (!userExists(split[1]))// check for username
                {
                    response = "Invalid Username";
                }
                else if (!userExists(split[1], split[2])) // check for username and corresponding password
                {
                    response = "Wrong Password";
                }
                else if (loggedUsers.ContainsKey(split[1]) ||
                    loggedUsers2.ContainsKey(socket.RemoteEndPoint.ToString())) //checks if user is on hashtree by the [KEY = username] or [KEY = IPAdress]
                {
                    int id;
                    if (loggedUsers2.TryGetValue(socket.RemoteEndPoint.ToString(), out id)) // O cliente já está logado com alguma conta
                    {
                        User user = getUser(id);
                        response = "You're allready Logged In As '" + user.username + "'";
                    }
                    else
                    { // O cliente não está logged in e está a tentar entrar numa contra logada noutro computador
                        response = "Another Computer is currently logged onto this account";
                    }
                }
                else
                {
                    Console.WriteLine(socket.RemoteEndPoint.ToString() + " loged in");
                    response = "Successfully Logging In";
                    //User user = new User(split[1], split[2]);
                    User user = getUser(split[1], split[2]); //split[1] = name, split[2] = password
                    loggedUsers.Add(user.username, user);
                    loggedUsers2.Add(socket.RemoteEndPoint.ToString(), user.ID);
                }
            }
            else if (command == "balance" && words == 1) // SHOW AVAILABLE CASH
            {
                if (loggedUsers2.ContainsKey(socket.RemoteEndPoint.ToString())) // Verifica se está logado
                {
                    int userID = loggedUsers2[socket.RemoteEndPoint.ToString()];
                    byte[] dataToSend = Encoding.ASCII.GetBytes("balance " + userID);
                    Stream stream = _cashierClient.GetStream();
                    stream.Write(dataToSend, 0, dataToSend.Length);
                    byte[] dataBuffer = new byte[1024];
                    int rec = stream.Read(dataBuffer, 0, 1024);
                    byte[] dataReceived = new byte[rec];
                    Array.Copy(dataBuffer, dataReceived, rec);
                    response = Encoding.ASCII.GetString(dataReceived);
                }
                else // Se não estiver logado...
                {
                    response = "You are not logged in";
                }
            }
            else if (command == "deposit" && words == 2)
            {
                if (loggedUsers2.ContainsKey(socket.RemoteEndPoint.ToString())) // Verifica se está logado
                {
                    string[] split = text.Split();
                    split[1] = split[1].Replace(".", ","); // Se o user escrever ####.## altera para ####,##
                    decimal value;
                    if (Decimal.TryParse(split[1], out value)) // It's a decimal
                    {
                        if (value < 10) // Abaixo da quantia minima
                        {
                            response = "Minimum Deposit 10 EUROS";
                        }
                        else // Quantia aceitavel
                        {
                            int userID = loggedUsers2[socket.RemoteEndPoint.ToString()];
                            byte[] dataToSend = Encoding.ASCII.GetBytes("deposit " + userID + " " + value);
                            Stream stream = _cashierClient.GetStream();
                            stream.Write(dataToSend, 0, dataToSend.Length);
                            byte[] dataBuffer = new byte[1024];
                            int rec = stream.Read(dataBuffer, 0, 1024);
                            byte[] dataReceived = new byte[rec];
                            Array.Copy(dataBuffer, dataReceived, rec);
                            response = Encoding.ASCII.GetString(dataReceived);
                        }
                    }
                    else // No it's not.
                    {
                        response = "Invalid Cash Format. Use 'deposit ####,##'";
                    }
                }
                else // Se não estiver logado...
                {
                    response = "You are not logged in";
                }
            }
            else // Comando inválido
            {
                response = "Invalid Request";
            }
            byte[] data = Encoding.ASCII.GetBytes(response);
            socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallBack), socket);
            socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket);
        }
        private static User getUser(string username, string password)
        {
            foreach (User user in registeredUsers)
            {
                if (user.username == username && user.password == password)
                    return user;
            }
            return null;
        }
        private static User getUser(int id)
        {
            foreach (User user in registeredUsers)
            {
                if (user.ID == id)
                    return user;
            }
            return null;
        }
        private static bool userExists(string username, string password)
        {
            foreach (User user in registeredUsers)
            {
                if (user.username == username && user.password == password)
                    return true;
            }
            return false;
        }
        private static bool userExists(string username)
        {
            foreach (User user in registeredUsers)
            {
                if (user.username == username)
                    return true;
            }
            return false;
        }
        private static void newUser(string username, string password)
        {
            User user = new User(username, password);
            registeredUsers.Add(user); // adiciona à lista de user's registados
            int userID = user.ID;
            byte[] dataToSend = Encoding.ASCII.GetBytes("register " + userID);
            Stream stream = _cashierClient.GetStream();
            stream.Write(dataToSend, 0, dataToSend.Length);
        }
        private static void SendCallBack(IAsyncResult AR)
        {
            Socket socket = (Socket)AR.AsyncState;
            socket.EndSend(AR);
        }
    }
}
客户机代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace Client
{
    class Program
    {
        private static Socket _clientSocket = new Socket
            (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        static void Main(string[] args)
        {
            Console.Title = "Client";
            LoopConnect();
            SendLoop();
            Console.ReadLine();
        }
        private static void SendLoop()
        {
            while (true)
            {
                Console.WriteLine("Enter a request: ");
                string req = Console.ReadLine();
                byte[] buffer = Encoding.ASCII.GetBytes(req);
                _clientSocket.Send(buffer);
                byte[] receivedBuf = new byte[1024];
                int rec = _clientSocket.Receive(receivedBuf);
                byte[] data = new byte[rec];
                Array.Copy(receivedBuf, data, rec);
                Console.WriteLine("Received: " + Encoding.ASCII.GetString(data));
            }
        }
        private static void LoopConnect()
        {
            int attempts = 0;
            while (!_clientSocket.Connected)
            {
                try
                {
                    attempts++;
                    _clientSocket.Connect(IPAddress.Loopback, 100);
                }
                catch (SocketException) {
                    Console.Clear();
                    Console.WriteLine("Connection attempts: " + attempts.ToString());
                }
            }
            Console.Clear();
            Console.WriteLine("Connected");
        }
    }
}

在这张打印图中,您可以看到正在运行的服务器和客户端。收银台对这个问题不重要。

http://goo.gl/wQZdb

客户端-服务器拍卖系统.控制台模式

定时器不必在单独的线程中。实际上,拍卖数据不需要在单独的线程中。您可以为此创建一个数据结构- auctions(类Auction, Owner, Participant, Bids),并将其存储在主线程中。您需要的是一个专门的线程,它可以不断检查拍卖数据结构(您可以将其存储在数据库或内存中,根据您的需要),以获取所有已经过的拍卖,并向所有拍卖参与者(所有者和参与者)发送通知。