在发布自己之前,我到处都在寻找这个问题的答案。我尝试过的一切对我来说都没有用。对于这个项目,我正在使用带有套接字的客户端-服务器模型在WPF中构建MasterMind游戏。建立连接后,服务器将随机选择一个答案,并处理用户所作的猜测。但是由于某种原因,只有第一个猜测才能正确通过该过程。此后,第二个猜测将返回与第一个猜测相同的响应-似乎是异常导致客户端返回了它从服务器接收到的前一个响应-而此后的猜测仅引发了一个不同的异常,表明该异常连接已关闭。我知道我的客户端没有关闭它,但是我不知道如何使服务器保持连接活动。我添加了一个“ keepAlive”选项,并且尝试了所有我所能找到的没有运气的东西。我在这里发布了相关的类,但是如果您想要完整的源代码并尝试实际运行它,则可以从我的github下载它:https://github.com/calewis1995/Games/tree/master/MasterMind2.0。
这是我的服务器:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace MMServer {
public class MMServer {
public static ManualResetEvent allDone = new ManualResetEvent(false);
private static MasterMind masterMind = null;
public MMServer() {}
public static void Main(string[] args) {
StartListening();
}
public static void StartListening() {
// Establish the local endpoint for the socket.
IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
// Bind the socket to the local endpoint and listen for incoming connections.
try {
listener.Bind(localEndPoint);
listener.Listen(100);
while (true) {
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
Console.Read();
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
masterMind = new MasterMind();
ServerStateObject state = new ServerStateObject {
workSocket = handler
};
handler.BeginReceive(state.buffer, 0, ServerStateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar) {
string content = string.Empty;
ServerStateObject state = (ServerStateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
handler.BeginReceive(state.buffer, 0, ServerStateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
Console.WriteLine("Player's Guess: {0}", content);
string reply = masterMind.GetReply(content.Replace("<EOF>", ""));
Send(handler, reply);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, ServerStateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, string data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar) {
try {
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
//handler.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
Console.Read();
}
}
}
}
这是我的客户:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
namespace MasterMind2._0 {
public class MMClient {
// The port number for the remote device.
private const int port = 11000;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static Socket clientSocket = null;
private static string response = string.Empty;
public static void StartClient() {
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
clientSocket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
clientSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), clientSocket);
connectDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public static string SendGuessAndReceiveAnswer(string guess) {
Send(clientSocket, guess + "<EOF>");
sendDone.WaitOne();
Receive(clientSocket);
receiveDone.WaitOne();
return response;
}
public static void Close() {
// Release the socket.
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
private static void ConnectCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client) {
try {
// Create the state object.
ClientStateObject state = new ClientStateObject {
workSocket = client
};
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, ClientStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar) {
try {
ClientStateObject state = (ClientStateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, ClientStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
} else {
// All the data has arrived; put it in response.
if (state.sb.Length > 1) {
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, string data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
}
}
这是WPF背后的c#,它与我的客户端套接字代码通信:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Drawing;
using MMServer;
namespace MasterMind2._0 {
public partial class MainWindow : Window {
private List<Ellipse> guessList;
private List<Ellipse> responseList;
private int ColorLimit { get; } = 4;
private Ellipse ellipse = null;
public MainWindow() {
InitializeComponent();
guessList = new List<Ellipse> { Guess1_1, Guess1_2, Guess1_3, Guess1_4,
Guess2_1, Guess2_2, Guess2_3, Guess2_4,
Guess3_1, Guess3_2, Guess3_3, Guess3_4,
Guess4_1, Guess4_2, Guess4_3, Guess4_4,
Guess5_1, Guess5_2, Guess5_3, Guess5_4,
Guess6_1, Guess6_2, Guess6_3, Guess6_4,
Guess7_1, Guess7_2, Guess7_3, Guess7_4,
Guess8_1, Guess8_2, Guess8_3, Guess8_4,
Guess9_1, Guess9_2, Guess9_3, Guess9_4,
Guess10_1, Guess10_2, Guess10_3, Guess10_4,
Guess11_1, Guess11_2, Guess11_3, Guess11_4,
Guess12_1, Guess12_2, Guess12_3, Guess12_4};
responseList = new List<Ellipse> { Response1_1, Response1_2, Response1_3, Response1_4,
Response2_1, Response2_2, Response2_3, Response2_4,
Response3_1, Response3_2, Response3_3, Response3_4,
Response4_1, Response4_2, Response4_3, Response4_4,
Response5_1, Response5_2, Response5_3, Response5_4,
Response6_1, Response6_2, Response6_3, Response6_4,
Response7_1, Response7_2, Response7_3, Response7_4,
Response8_1, Response8_2, Response8_3, Response8_4,
Response9_1, Response9_2, Response9_3, Response9_4,
Response10_1, Response10_2, Response10_3, Response10_4,
Response11_1, Response11_2, Response11_3, Response11_4,
Response12_1, Response12_2, Response12_3, Response12_4};
MMClient.StartClient();
}
private void NewGameButton_Click(object sender, RoutedEventArgs e) {
}
private void SubmitButton_Click(object sender, RoutedEventArgs e) {
int numOfColors = 0;
string guess = "";
foreach (Ellipse el in guessList) {
if (el.IsEnabled && numOfColors < 4) {
System.Drawing.ColorConverter converter = new System.Drawing.ColorConverter();
System.Drawing.Color color = (System.Drawing.Color)converter.ConvertFromString(el.Fill.ToString());
KnownColor knownColor = color.ToKnownColor();
string colorString = knownColor.ToString();
guess += colorString + " ";
numOfColors++;
el.IsEnabled = false;
}
}
guess = guess.TrimEnd(' ');
string response = MMClient.SendGuessAndReceiveAnswer(guess).Replace("<EOF>", "");
ProcessResponse(response);
}
private void ProcessResponse(string response) {
if (response.Contains(MasterMind.youLose)) {
MessageBox.Show(response, "Game Over", MessageBoxButton.OK, MessageBoxImage.Information);
} else if (response.Equals(MasterMind.nextGuess)) {
MessageBox.Show(response, "Empty Guess", MessageBoxButton.OK, MessageBoxImage.Error);
} else if (response.Equals(MasterMind.youWin)) {
MessageBox.Show(response, "Game Over", MessageBoxButton.OK, MessageBoxImage.Information);
} else {
int index = 0;
foreach (Ellipse el in responseList) {
if (index < response.Length) {
if (el.IsEnabled) {
BrushConverter converter = new BrushConverter();
if (response[index] == 'W') {
System.Windows.Media.Brush newFill = (System.Windows.Media.Brush)converter.ConvertFromString("White");
el.Fill = newFill;
} else if (response[index] == 'B') {
System.Windows.Media.Brush newFill = (System.Windows.Media.Brush)converter.ConvertFromString("Black");
el.Fill = newFill;
}
index++;
el.IsEnabled = false;
}
}
}
}
}
protected override void OnMouseDown(MouseButtonEventArgs e) {
base.OnMouseDown(e);
ellipse = (Ellipse)e.Source;
}
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
if (e.LeftButton == MouseButtonState.Pressed) {
DataObject data = new DataObject();
data.SetData(DataFormats.StringFormat, ellipse.Fill.ToString());
data.SetData("Object", ellipse);
DragDrop.DoDragDrop(ellipse, data, DragDropEffects.Copy);
}
}
private void Guess_DragOver(object sender, DragEventArgs e) {
e.Effects = DragDropEffects.Copy;
}
private void Guess_OnDrop(object sender, DragEventArgs e) {
if (e.Data.GetDataPresent(DataFormats.StringFormat)) {
string color = (string)e.Data.GetData(DataFormats.StringFormat);
BrushConverter converter = new BrushConverter();
if (converter.IsValid(color)) {
System.Windows.Media.Brush newFill = (System.Windows.Media.Brush)converter.ConvertFromString(color);
((Ellipse)sender).Fill = newFill;
}
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
MMClient.Close();
}
}
}
任何帮助将不胜感激。谢谢!