下面是socket服务器的基本方面:(由于显而易见的原因,很多时候已经取出)
如何更改此设置以便它可以处理并发连接?我应该对每个回复进行线程化吗?
由于
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"));
}
}
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")
{
}
}
}
}
}
答案 0 :(得分:1)
您将不需要使用同步函数,但需要使用像Socket.BeginReceive这样的asynchrounus函数
答案 1 :(得分:0)
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(); } } }
答案 2 :(得分:-1)
首先:停止使用非阻塞套接字。在.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。该代码只是一个小指南,可以帮助您前进。