[英]C# Socket Server - Issue with Concurrent Connections
嘿,我已經用C#為正在開發的Flash游戲制作了一個套接字服務器,我從某個地方獲得了代碼,並且我是c#和.net開發的初學者。 實際上,當建立連接並且服務器正常運行時,它可以正常工作。 同時獲得2個並發連接,我們遇到了問題。
以下是套接字服務器的基本方面:(出於明顯的原因而取出)
我怎樣才能改變它,使其可以處理並發連接? 我應該在每個響應中添加線索嗎?
謝謝
class TcpSock { int tcpIndx = 0; int tcpByte = 0;
byte[] tcpRecv = new byte[1024]; //////////////////////////////////////// public Socket tcpSock; //////////////////////////////////////// public int Recv(ref string tcpRead) { tcpByte = tcpSock.Available; if (tcpByte > tcpRecv.Length - tcpIndx) tcpByte = tcpRecv.Length - tcpIndx; tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte, SocketFlags.Partial); tcpRead = Encoding.ASCII.GetString (tcpRecv, tcpIndx, tcpByte); tcpIndx += tcpByte; return tcpRead.Length; } public int RecvLn(ref string tcpRead) { tcpRead = Encoding.ASCII.GetString (tcpRecv, 0, tcpIndx); tcpIndx = 0; return tcpRead.Length; } public int Send(string tcpWrite) { return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite)); } public int SendLn(string tcpWrite) { return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\\r\\n")); } }
[STAThread] static void Main() {
Thread Server1 = new Thread(RunServer); Server1.Start(); } static void RunServer() { ///class IPHostEntry : Stores information about the Host and is required ///for IPEndPoint. ///class IPEndPoint : Stores information about the Host IP Address and ///the Port number. ///class TcpSock : Invokes the constructor and creates an instance. ///class ArrayList : Stores a dynamic array of Client TcpSock objects. IPHostEntry Iphe = Dns.Resolve(Dns.GetHostName()); IPEndPoint Ipep = new IPEndPoint(Iphe.AddressList[0], 4444); Socket Server = new Socket(Ipep.Address.AddressFamily,SocketType.Stream, ProtocolType.Tcp); ///Initialize ///Capacity : Maximux number of clients able to connect. ///Blocking : Determines if the Server TcpSock will stop code execution ///to receive data from the Client TcpSock. ///Bind : Binds the Server TcpSock to the Host IP Address and the Port Number. ///Listen : Begin listening to the Port; it is now ready to accept connections. ArrayList Client = new ArrayList(); string[,] Users = new string[1000,9]; string rln = null; string[] Data; Client.Capacity = 1000; Server.Blocking = false; Server.Bind(Ipep); Server.Listen(32); Console.WriteLine("Server 1 {0}: listening to port {1}", Dns.GetHostName(), Ipep.Port); //////////////////////////////////////////////////////////////////////////////////////////// ///Main loop ///1. Poll the Server TcpSock; if true then accept the new connection. ///2. Poll the Client TcpSock; if true then receive data from Clients. while (true) { //Accept - new connection #region new connection if (Server.Poll(0, SelectMode.SelectRead)) { int i = Client.Add(new TcpSock()); ((TcpSock)Client[i]).tcpSock = Server.Accept(); Console.WriteLine("Client " + i + " connected."); Users[i, 0] = i.ToString(); } #endregion for (int i = 0; i < Client.Count; i++) { //check for incoming data if (((TcpSock)Client[i]).tcpSock.Poll(0, SelectMode.SelectRead)) { //receive incoming data if (((TcpSock)Client[i]).Recv(ref rln) > 0) { Console.WriteLine(rln.ToString()); Data = rln.Split('|'); // 1) initial connection #region InitialConnection if (Data[0] == "0000") { } } } } }
}
您無需使用同步函數,而可以使用諸如Socket.BeginReceive之類的異步函數。
using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text;
public static partial class TcpServer { public static void Main() { // Setup listener on "localhost" port 12000 IPAddress ipAddr = Dns.GetHostEntry("localhost").AddressList[0]; TcpListener server = new TcpListener(ipAddr, 12000); server.Start(); // Network driver can now allow incoming requests // Accept up to 1 client per CPU simultaneously Int32 numConcurrentClients = Environment.ProcessorCount; for (Int32 n = 0; nprivate static Byte[] ProcessData(Byte[] inputData) { String inputString = Encoding.UTF8.GetString(inputData, 1, inputData[0]); String outputString = inputString.ToUpperInvariant(); Console.WriteLine("Input={0}", inputString); Console.WriteLine(" Output={0}", outputString); Console.WriteLine(); Byte[] outputStringBytes = Encoding.UTF8.GetBytes(outputString); Byte[] outputData = new Byte[1 + outputStringBytes.Length]; outputData[0] = (Byte)outputStringBytes.Length; Array.Copy(outputStringBytes, 0, outputData, 1, outputStringBytes.Length); return outputData; } }public static partial class TcpServer { private sealed class ClientConnectionApm { private TcpListener m_server; private TcpClient m_client; private Stream m_stream; private Byte[] m_inputData = new Byte[1]; private Byte m_bytesReadSoFar = 0;public ClientConnectionApm(TcpListener server) { m_server = server; m_server.BeginAcceptTcpClient(AcceptCompleted, null); }private void AcceptCompleted(IAsyncResult ar) { // Connect to this client m_client = m_server.EndAcceptTcpClient(ar); // Accept another client new ClientConnectionApm(m_server); // Start processing this client m_stream = m_client.GetStream(); // Read 1 byte from client which contains length of additional data m_stream.BeginRead(m_inputData, 0, 1, ReadLengthCompleted, null); }private void ReadLengthCompleted(IAsyncResult result) { // If client closed connection; abandon this client request if (m_stream.EndRead(result) == 0) { m_client.Close(); return; } // Start to read 'length' bytes of data from client Int32 dataLength = m_inputData[0]; Array.Resize(ref m_inputData, 1 + dataLength); m_stream.BeginRead(m_inputData, 1, dataLength, ReadDataCompleted, null); }private void ReadDataCompleted(IAsyncResult ar) { // Get number of bytes read from client Int32 numBytesReadThisTime = m_stream.EndRead(ar); // If client closed connection; abandon this client request if (numBytesReadThisTime == 0) { m_client.Close(); return; } // Continue to read bytes from client until all bytes are in m_bytesReadSoFar += (Byte)numBytesReadThisTime; if (m_bytesReadSoFar private void WriteDataCompleted(IAsyncResult ar) { // After result is written to client, close the connection m_stream.EndWrite(ar); m_client.Close(); } } }
首先:停止使用非阻塞套接字。 在.NET中,您應該堅持使用同步方法Receive
/ Send
或異步方法BeginReceive
/ BeginSend
。
如果只有少數幾個客戶端,則只應堅持使用同步方法。 然后在新線程中啟動每個新客戶端。 這是一切運行的最簡單選擇。
只需這樣做:
public void AcceptClients()
{
TcpListener listener = new TcpListener(IPAddress.Any, 5566);
listener.Start();
while (_serverRunning)
{
var socket = listener.AcceptSocket();
new Thread(ClientFunc).Start(socket);
}
}
public void ClientFun(object state)
{
var clientSocket = (Socket)state;
var buffer = new byte[65535];
while (_serverRunning)
{
//blocking read.
clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
//check packet.
// handle packet
// send respons.
clientSocket.Send(alalalal);
}
}
您應該重構這些方法,以便它們遵循SRP。 該代碼只是幫助您入門的一個小指南。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.