我正在使用C#套接字。我正在做一个拍卖服务器和客户端项目。控制台模式。
实际上,我有1个服务器为多个客户端异步运行。
主要问题:1次拍卖结束时,服务器必须将消息发送给获胜者(如果存在),卖方和宽松者。我需要一种时钟来触发事件。
在客户端上,我可以发送以下命令:
现在,我在拍卖系统的逻辑上遇到了麻烦。
当服务器读取(命令==“creat”)时,它必须使用相应的信息来创建拍卖。
如何才能做到这一点?每次拍卖有1个线程?
当时间结束时,服务器必须重新执行以下操作:
我以为:
可以执行此伪代码吗?
我必须使用哪些类?
服务器代码:
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数据结构(可以将其存储在数据库或内存中,以满足您的需要),以获取已过去的所有拍卖并将通知发送给所有拍卖参与者(所有者和参与者) )。