在我的C#服务器-客户端程序中,我有以下问题:
使用客户机之一登录到服务器后,在与IP连接并键入“ LOGIN xxxxxxx”后,服务器自动通过StackOverFlowException关闭。
客户代码
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace SIKTcpClient
{
class Program
{
private const int Port = 3000;
private static Socket _socket;
private const int attemptsLimit = 2;
private const int BufferSize = 2048;
private static byte[] buffer = new Byte[BufferSize];
private static string _login;
static void Main(string[] args)
{
Console.WriteLine("Write ip adress");
var input = Console.ReadLine();
var ipAdress = input.Length < 2 ? GetIpAdress() : input;
if (input.Length < 2)
Console.WriteLine(ipAdress);
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Connect(ipAdress);
Console.WriteLine("Your login");
try
{
if (input.Length < 2)
{
Console.WriteLine(_login);
_socket.Send(Encoding.ASCII.GetBytes(_login));
}
while (true)
{
var result = Console.ReadLine();
var bytes = Encoding.ASCII.GetBytes(result);
_socket.Send(bytes);
}
}
catch (SocketException)
{
Console.WriteLine("Server was shut down.");
}
catch(Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
static void Connect(string ipAdress)
{
var attempts = 0;
while (!_socket.Connected && attempts < attemptsLimit)
{
try
{
++attempts;
var result = _socket.BeginConnect(ipAdress, Port, EndConnect, null);
result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3));
Thread.Sleep(3000);
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
if(!_socket.Connected)
{
Console.WriteLine("Could not connect to server");
return;
}
}
private static void EndConnect(IAsyncResult asyncResult)
{
try
{
_socket.EndConnect(asyncResult);
if (_socket.Connected)
{
_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _socket);
}
else
{
Console.WriteLine("End of connection attempt, fail to connect...");
}
}
catch (SocketException)
{
Console.WriteLine("Waiting for server...");
}
catch(Exception ex)
{
Console.WriteLine("Cant connnect to server... " + ex.Message);
}
}
private static void ReceiveCallback(IAsyncResult asyncResult)
{
try
{
var socket = (Socket)asyncResult.AsyncState;
if (socket.Connected)
{
var received = socket.EndReceive(asyncResult);
if (received > 0)
{
var data = new byte[received];
Buffer.BlockCopy(buffer, 0, data, 0, data.Length);
var message = Encoding.UTF8.GetString(data);
if (!string.IsNullOrWhiteSpace(message))
Console.Write("Server: " + Encoding.UTF8.GetString(data));
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
}
}
}
catch(SocketException)
{
Console.WriteLine("Server was shut down.");
}
catch(Exception ex)
{
Console.WriteLine("Receive callback failed "+ ex.Message);
}
}
private static string GetIpAdress()
{
var random = new Random();
var r = random.Next(100000000);
_login = "LOGIN " + r;
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
socket.Connect("8.8.8.8", 65530);
var endPoint = socket.LocalEndPoint as IPEndPoint;
var localIP = endPoint.Address.ToString();
return localIP;
}
}
}
}
服务器代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SIKTcpServer.Constants;
using SIKTcpServer.Models;
using SIKTcpServer.Models.Cards;
namespace SIKTcpServer
{
class Program
{
private static Socket _socket;
private const int Port = 3000;
private const int BufferSize = 2048;
private static byte[] _buffer = new byte[BufferSize];
private static List<Player> _players = new List<Player>();
private static bool _gameStarted = false;
private static List<Player> _playersInRound;
private static readonly int[] _ids = new int[5] { 1, 2, 3, 4, 5 };
private static List<AbstractCard> _turnCards;
static void Main(string[] args)
{
Console.Title = "Server";
GatherPlayers();
Console.ReadKey();
}
private static void GatherPlayers()
{
//var a = LoadCards();
Console.WriteLine("Waiting for players...");
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.Bind(new IPEndPoint(IPAddress.Any, Port));
_socket.Listen(0);
_socket.BeginAccept(new AsyncCallback(AcceptCallback), null);
while(_players.Count < 2) { }
Console.WriteLine("asd");
}
private static void AcceptCallback(IAsyncResult asyncResult)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
socket = _socket.EndAccept(asyncResult);
if (_players.Count > 2 || _gameStarted)
{
socket.Send(GetAsciiBytes("Sorry we have 5 players already"));
return;
}
socket.Send(GetAsciiBytes("CONNECT"));
Console.WriteLine("Connected new socket");
socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
_socket.BeginAccept(new AsyncCallback(AcceptCallback), socket);
}
catch
{
RemovePlayer(socket);
socket.Dispose();
}
}
private static void ReceiveCallback(IAsyncResult asyncResult)
{
Socket current = (Socket)asyncResult.AsyncState;
int received;
try
{
received = current.EndReceive(asyncResult);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
current.Close();
RemovePlayer(current);
return;
}
byte[] recBuffer = new byte[received];
Array.Copy(_buffer, recBuffer, received);
string text = Encoding.ASCII.GetString(recBuffer);
Console.WriteLine("Received Text: " + text);
if (_players.Count > 4)
{
current.Send(GetAsciiBytes("Sorry we have 5 players already"));
current.Close();
current.Dispose();
}
else if (text.Length < 7 || text.Substring(0, 5) != "LOGIN" || string.IsNullOrWhiteSpace(text.Substring(6, 2)))
{
Console.WriteLine("Text is an invalid request");
var data = Encoding.ASCII.GetBytes("Invalid request");
current.Send(data);
Console.WriteLine("Warning Sent");
current.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceiveCallback, current);
}
else
{
current.Send(GetAsciiBytes("OK"));
_players.Add(new Player(current));
Console.WriteLine("Player OK");
}
}
private static void Round()
{
StartRound();
while (_playersInRound.Count > 1 && _turnCards.Count > 0)
{
foreach (var player in _playersInRound)
{
if (player.IsEliminated)
{
}
if (player.SkipTurn)
{
player.SkipTurn = false;
continue;
}
var card = GetRandomCard();
player.Cards.Add(card);
player.Socket.Send(GetAsciiBytes($"YOUR MOVE {card.Name}"));
var playerCardsNames = player.Cards.Select(x => x.Name).ToArray();
if (player.HaveCountessAndKingOrPrince)
{
while(true)
{
player.Socket.Receive(_buffer, 0, _buffer.Length, SocketFlags.None);
}
}
var splittedMessage = GetStringFromBytes(_buffer).Split(new char[0]);
var choosenPlayer = Int32.Parse(splittedMessage[2] ?? "0");
var choosenSecondCard = splittedMessage[3] ?? "";
var playedCard = player.Cards.Where(x => x.Name.ToString() == splittedMessage[1]).First();
player.Cards.Where(x => x.Name == playedCard.Name).FirstOrDefault().Action(player, _playersInRound.Where(x => x.Id == choosenPlayer).FirstOrDefault(), choosenSecondCard);
//Array.Clear(_buffer, 0, _buffer.Length);
RemoveEliminatedPlayers();
}
}
}
private static void StartRound()
{
MixPlayers();
LoadCards();
GiveStartingCardsToPlayers();
foreach (var player in _playersInRound)
{
player.Socket.Send(GetAsciiBytes($"START {player.Id.ToString()} {player.Cards[0]}"));
}
}
private static void MixPlayers()
{
var ids = _ids.ToList();
var random = new Random();
for (var i = 0; i < 5; i++)
{
var randomListIndex = random.Next(ids.Count);
_playersInRound[i].Id = ids[randomListIndex];
ids.RemoveAt(randomListIndex);
}
_playersInRound.OrderBy(x => x.Id);
}
private static void RemovePlayer(Socket socket)
{
_players.Remove(_players.Where(x => x.Socket == socket).FirstOrDefault());
}
private static List<AbstractCard> LoadCards()
{
var allCards = new List<AbstractCard>();
var values = Enum.GetValues(typeof(CardName)).Cast<CardName>().ToArray();
foreach (var value in values)
{
for (var i = 0; i < (int)Enum.Parse(typeof(CardAmount), value.ToString()); i++)
{
switch (value)
{
case CardName.Baron:
allCards.Add(new BaronCard());
break;
case CardName.Countess:
allCards.Add(new CountessCard());
break;
case CardName.Guard:
allCards.Add(new GuardCard());
break;
case CardName.Handmaiden:
allCards.Add(new HandmaidenCard());
break;
case CardName.King:
allCards.Add(new KingCard());
break;
case CardName.Priest:
allCards.Add(new PriestCard());
break;
case CardName.Prince:
allCards.Add(new PrinceCard());
break;
case CardName.Princess:
allCards.Add(new PrincessCard());
break;
}
}
}
return allCards;
}
private static AbstractCard GetRandomCard()
{
var random = new Random();
var randomIndex = random.Next(_turnCards.Count);
var randomCard = _turnCards[randomIndex];
_turnCards.RemoveAt(randomIndex);
return randomCard;
}
private static void GiveStartingCardsToPlayers()
{
foreach (var player in _playersInRound)
{
player.Cards.Add(GetRandomCard());
}
}
private static void RemoveEliminatedPlayers()
{
Predicate<Player> eliminated = (Player player) => { return player.IsEliminated == true; };
_playersInRound.RemoveAll(eliminated);
_players.ForEach(x => x.ClearElimination());
}
private static byte[] GetAsciiBytes(string text)
{
return Encoding.ASCII.GetBytes(text);
}
private static string GetStringFromBytes(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
}
}
一个糟糕的stackoverflow网站说,我的帖子似乎主要是代码,但是我已经描述了上面的所有内容,因此在这里对此毫无意义的文字表示抱歉。
答案 0 :(得分:0)
您已经创建了一个静态缓冲区数组,该数组向您发出stackoverflow异常,这是因为多个客户端同时请求。他们都使用了这个静态缓冲区。在开发中创建静态缓冲区不是一个好方法。 您必须提出这样的一些新登录信息。
public class SocketPacketforROD
{
public System.Net.Sockets.Socket CurrentSocket;
//test
public int last_buffer_read = 0;
public int last_socket_payload_size = 0;
public byte[] Data = null; // new byte[Server.bufferLength];
public SocketPacketforROD_State m_state = SocketPacketforROD_State.socket_state_payload_size;
public void allocate(int bytes)
{
// socket_buffer_length = bytes;
Data = new byte[bytes];
}
}
在您的onreceiveddata方法中使用了此套接字对象类
string Data = Encoding.ASCII.GetString(socketData.Data);
Logger.WriteLog("Message Received length : " + Data.Length + " from: " + socketData.CurrentSocket.RemoteEndPoint, LogLevel.GENERALLOG);
socketData.m_state = SocketPacketforROD_State.socket_state_payload_size;
设置接收回叫
private void SetupReceiveCallback(Socket objClientSocket)
{
try
{
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
SocketPacketforROD theSocPkt = new SocketPacketforROD();
theSocPkt.last_socket_payload_size = 4;
theSocPkt.allocate(4);
theSocPkt.CurrentSocket = objClientSocket;
Logger.WriteLog("After New Socket buffer Length : " + theSocPkt.Data.Length, LogLevel.GENERALLOG);
objClientSocket.BeginReceive(theSocPkt.Data, 0, theSocPkt.Data.Length, SocketFlags.None, recieveData, theSocPkt);
}
catch (OutOfMemoryException MemEXP)
{
Logger.WriteException(MemEXP);
}
catch (Exception E)
{
Logger.WriteException(E);
}
}