我正处于编写新的Windows服务应用程序的设计阶段,该应用程序接受长连接的TCP/IP连接(即,这不像HTTP,其中有许多短连接,而是客户端连接并保持连接数小时或数天或甚至几周).
我正在寻找设计网络架构的最佳方法的想法.我将需要为该服务启动至少一个线程.我正在考虑使用Asynch API(BeginRecieve等),因为我不知道在任何给定时间(可能是数百个)我将连接多少客户端.我绝对不想为每个连接启动一个线程.
数据将主要从我的服务器流向客户端,但有时会从客户端发送一些命令.这主要是一个监控应用程序,我的服务器定期向客户端发送状态数据.
有关尽可能扩展的最佳方法的任何建议吗?基本工作流程 谢谢.
编辑:要明确,我正在寻找基于.net的解决方案(如果可能,C#,但任何.net语言都可以)
BOUNTY注意:要获得赏金,我希望不仅仅是一个简单的答案.我需要一个解决方案的工作示例,作为指向我可以下载的内容的指针或在线的简短示例.它必须是基于.net和Windows(任何.net语言都可以接受)
编辑:我要感谢所有给出好答案的人.不幸的是,我只能接受一个,我选择接受更为人熟知的Begin/End方法.Esac的解决方案可能会更好,但它仍然足够新,我不确定它将如何运作.
我已经提出了我认为很好的所有答案,我希望我能为你们做更多的事情.再次感谢.
这是我的另一个问题的一个分支.如果你愿意,请阅读它,但没有必要.
基本上,我意识到为了在大型消息上有效地使用C#的BeginReceive(),我需要(a)首先读取数据包长度,然后准确读取多个字节或(b)使用数据包结束分隔符.我的问题是,这些都存在于协议缓冲区中吗?我还没有使用过它们,但是在文档中看起来似乎没有长度标题或分隔符.
如果没有,我该怎么办?我应该只构建消息,然后用长度标题/ EOP分隔符前缀/后缀吗?
我最近在C#中编写了一个快速而肮脏的概念验证代理服务器,作为使Java Web应用程序与驻留在另一台服务器上的传统VB6应用程序进行通信的努力的一部分.这简直太荒谬了:
代理服务器和客户端都使用相同的消息格式; 在代码中我使用一个ProxyMessage类来表示来自客户端的请求和服务器生成的响应:
public class ProxyMessage
{
int Length; // message length (not including the length bytes themselves)
string Body; // an XML string containing a request/response
// writes this message instance in the proper network format to stream
// (helper for response messages)
WriteToStream(Stream stream) { ... }
}
Run Code Online (Sandbox Code Playgroud)
消息尽可能简单:正文的长度+消息正文.
我有一个单独的ProxyClient类,表示与客户端的连接.它处理代理和单个客户端之间的所有交互.
我想知道的是它们是简化与异步套接字编程相关的样板代码的设计模式还是最佳实践?例如,您需要注意管理读取缓冲区,以免意外丢失字节,并且需要跟踪处理当前消息的距离.在我当前的代码中,我在我的回调函数中完成所有这些工作TcpClient.BeginRead,并在一些实例变量的帮助下管理缓冲区的状态和当前的消息处理状态.
我传递给我的回调函数的代码BeginRead如下,以及上下文的相关实例变量.代码似乎工作正常"原样",但我想知道它是否可以重构一点以使其更清晰(或者它可能已经是?).
private enum BufferStates
{
GetMessageLength,
GetMessageBody
}
// The read buffer. Initially 4 bytes because we are …Run Code Online (Sandbox Code Playgroud) 我希望对以下内容有所帮助.这与异步套接字有关.
来自发件人:
string stringData = "Welcome to my server server server";
byte[] message1 = Encoding.ASCII.GetBytes(stringData);
//MessageBox.Show(message1.Length.ToString());
client.BeginSend(message1, 0, message1.Length, SocketFlags.None, new AsyncCallback(SendData), client);
Run Code Online (Sandbox Code Playgroud)
在这里可以看到,可以找到message.length.
-
在客户端:
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceive(iar);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
Run Code Online (Sandbox Code Playgroud)
我的问题是有没有办法访问发送数据的实际长度,并根据该调用接收数据,直到收到完整的消息?