[英]How to connect to modems with tcp clients, in multiple port or other way?
我有大約5000個調制解調器(瘦客戶端),我想與他們通信,我的方法之一是這樣的: string GetModemData(modemID)
,現在我有一個服務器中的開放端口,監聽調制解調器,我正在使用socket編程將數據發送到調制解調器(調用相關函數),但是當我想在同一時間向多個調制解調器發送數據並從中獲取響應時,我不知道該怎么辦? 我可以將數據發送到一個調制解調器並等待其響應,然后將其他數據發送到其他調制解調器(順序),但問題是客戶端應該等待很長時間才能得到答案(可能是某些不同的客戶端希望從調制解調器獲取一些信息所以他們都會等到Q或類似的東西),我認為解決這個問題的一種方法是使用多個端口並監聽每個調制解調器到相關的端口,但它需要太多的端口,也可能是內存使用量up並超過我的可用內存空間,因此可能會發生一些丟失(這是真的嗎?)。 該怎么辦? 我考慮並行,但我認為它不相關我應該等待一個端口,因為我不知道應該將當前接收的數據傳遞給哪個客戶端。 我正在使用asp.net。
目前我這樣做:
private void StartListener()
{
ModemTcpListener = new TcpListener(ModemPort);
//ClientTcpListener = new TcpListener(ClientPort);
ModemTcpListener.Start();
ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
}
作為回報
private void DoReadModemCallback(IAsyncResult ar)
{
try
{
bool bRet = ar.AsyncWaitHandle.WaitOne(420000);
Modem modem = ar.AsyncState as Modem;
if (!bRet || modem == null)
{
return;
}
}
catch{}
// now send data to which client?????? if i'm going to use async????
}
並且:
private void DoAcceptModemCallback(IAsyncResult ar)
{
try
{
ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
TcpClient tcpClient = ModemTcpListener.EndAcceptTcpClient(ar);
Modem modem= new Modem(tcpClient, "");
tcpClient.GetStream().BeginRead(modem.Buffer, 0, tcpClient.ReceiveBufferSize, new AsyncCallback(DoReadModemCallback), modem);
ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
Log.Write("a Modem connect ...");
}
catch (Exception ex)
{
}
}
這是一個跟蹤所有客戶的例子。 為了便於閱讀,我已經壓縮了它。 你應該把它分成多個類。
我正在使用Pool(我剛創建並提交)和SimpleServer。 這兩個類都是我正在構建的庫的一部分(但遠未完成)。
不要害怕打開5000個套接字,在使用異步操作時它們不會占用太多資源。
public class SuperServer
{
private List<ClientContext> _clients = new List<ClientContext>();
private SimpleServer _server;
private Pool<byte[]> _bufferPool;
public SuperServer()
{
// Create a buffer pool to be able to reuse buffers
// since your clients will most likely connect and disconnect
// often.
//
// The pool takes a anonymous function which should return a new buffer.
_bufferPool = new Pool<byte[]>(() => new byte[65535]);
}
public void Start(IPEndPoint listenAddress)
{
_server = new SimpleServer(listenAddress, OnAcceptedSocket);
// Allow five connections to be queued (to be accepted)
_server.Start(5);
}
// you should handle exceptions for the BeginSend
// and remove the client accordingly.
public void SendToAll(byte[] info)
{
lock (_clients)
{
foreach (var client in _clients)
client.Socket.BeginSend(info, 0, info.Length, SocketFlags.None, null, null);
}
}
// Server have accepted a new client.
private void OnAcceptedSocket(Socket socket)
{
var context = new ClientContext();
context.Inbuffer = _bufferPool.Dequeue();
context.Socket = socket;
lock (_clients)
_clients.Add(context);
// this method will eat very few resources and
// there should be no problem having 5000 waiting sockets.
context.Socket.BeginReceive(context.Inbuffer, 0, context.Inbuffer.Length, SocketFlags.None, OnRead,
context);
}
//Woho! You have received data from one of the clients.
private void OnRead(IAsyncResult ar)
{
var context = (ClientContext) ar.AsyncState;
try
{
var bytesRead = context.Socket.EndReceive(ar);
if (bytesRead == 0)
{
HandleClientDisconnection(context);
return;
}
// process context.Inbuffer here.
}
catch (Exception err)
{
//log exception here.
HandleClientDisconnection(context);
return;
}
// use a new try/catch to make sure that we start
// read again event if processing of last bytes failed.
try
{
context.Socket.BeginReceive(context.Inbuffer, 0, context.Inbuffer.Length, SocketFlags.None, OnRead,
context);
}
catch (Exception err)
{
//log exception here.
HandleClientDisconnection(context);
}
}
// A client have disconnected.
private void HandleClientDisconnection(ClientContext context)
{
_bufferPool.Enqueue(context.Inbuffer);
try
{
context.Socket.Close();
lock (_clients)
_clients.Remove(context);
}
catch(Exception err)
{
//log exception
}
}
// One of your modems
// add your own state info.
private class ClientContext
{
public byte[] Inbuffer;
public Socket Socket;
}
}
使用的類:
您需要使用異步tcp / ip方法。 本文介紹如何:
http://www.codeproject.com/KB/IP/asyncsockets.aspx
關鍵部分是BeginReceive()和相關的回調函數。 還有q,請在這個答案留下評論;)最好的運氣!
您需要多線程,每當客戶端建立與服務器的連接時,為它啟動一個新線程並開始通信發送/接收。
以下是一些解釋c#, sc -sharpcorner 代碼項目中多線程的文章
這是一個帶有多線程的示例服務器應用程序, http://www.dotnetspider.com/resources/2829-A-multi-readed-server-C-which-finds-prime-num.aspx
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.