我有一个问题,根据两个网络设备的启动顺序,我似乎失去了在一端接收数据的能力。
设置是一个用 C# (.NET 4.0) 编写的小型服务器,它监听来自工业扫描仪的数据的特定端口,通过 TCP 进行通信。扫描器可以很好地连接到服务器应用程序,并将发送服务器接收和处理的小数据 block (序列号)。但是,在扫描仪上重新启动(实际上,循环电源,并不能优雅地关闭其连接)会导致服务器停止处理数据。事件的顺序以及导致问题的关键网络流量如下:
SUCCESS FAILURE
|----------------------| |----------------------|
| SCANNER | SERVER | | SCANNER | SERVER |
|----------------------| |----------------------|
| | Starts | | Starts | |
| Starts | | | | Starts |
| Scan | Received | | Scan | Received |
| Restarts | | | Restarts | |
--------(Network)------- --------(Network)-------
| SYN | | | SYN | |
| | ACK-123 | | | SYN ACK |
| RST - 123 | | | ACK | |
| SYN | | | | |
| | SYN ACK | | | |
| ACK | | | | |
|----------------------| |----------------------|
| Scan | Received | | Scan | !LOST! |
|----------------------| |----------------------|
如您所见,在 SUCCESS 场景中,扫描器重新启动后,服务器使用 ACK 响应 SYN,并且扫描器重置连接,因为它意识到它不在正确的流中。服务器检测到这一点并优雅地处理它。然而,在 FAILURE 场景中,服务器很高兴地用 SYN ACK 响应,扫描器 ACK,并建立了新的连接。
代码没有提示任何事情,但是我的 TcpLister/TcpClient 似乎再也没有接收到任何数据,即使在 Wireshark 中看到它被接收和确认时也是如此。似乎 TcpListener 和处理程序仍在等待旧连接以获取数据?我是这个级别的网络编程的新手(对于 C# 本身也是相对较新的),所以如果我遗漏了一些明显的东西,一定要指出。
服务器代码片段:
public void Run()
{
while (!shutdown)
{
shutdown = false; // Reset
listenerServer = new TcpListener(IPAddress.Any, scanner.Address.Port);
try
{
listenerServer.Start();
TcpClient handler = listenerServer.AcceptTcpClient();
while (true)
{
try
{
incomingData = null;
dataBuffer = new Byte[256];
NetworkStream stream = handler.GetStream(); // blocks here
int i;
while ((i = stream.Read(dataBuffer, 0, dataBuffer.Length)) != 0)
{
incomingData += Encoding.ASCII.GetString(dataBuffer, 0, i);
int startIndex = incomingData.IndexOf(startMarker);
int endIndex = incomingData.IndexOf(endMarker);
if (startIndex > -1 && endIndex > -1)
{
string serialData = incomingData.Substring(startIndex + 1, endIndex - startIndex - 1);
scanner.ProcessDataChange(serialData);
}
}
}
catch (IOException e)
{
// Deals with SocketExceptions here...
}
finally
{
handler.Close();
}
}
}
catch (SocketException e)
{
listenerServer.Stop();
listenerServer = null;
}
finally
{
listenerServer.Stop();
listenerServer = null;
}
}
}
最佳答案
用户 @LB (L. B)回答了一个问题,但认为它可能无关紧要而将其删除。事实上,这是对这个问题的一个很好的回答,所以我在这里重新发布它。最后,我没有听取正在建立的新联系。 如果 L. B 希望重新发布他的答案,我会很乐意接受。
你只接受一个与 TcpClient 的连接 handler = listenerServer.AcceptTcpClient();
当第一个连接关闭时,您不再接受连接。您应该将它移到 while 循环中。
编辑
这不是对您问题的直接回答。但是我尝试了下面的代码并且效果很好。如果你愿意,你可以试试。我稍后会删除此答案。
void Run()
{
TcpListener listener = new TcpListener(IPAddress.Any, 12345);
listener.Start();
Task.Factory.StartNew(() =>
{
while (true)
{
var client = listener.AcceptTcpClient();
Task.Factory.StartNew(() => Handler(client), TaskCreationOptions.LongRunning);
}
}, TaskCreationOptions.LongRunning);
}
void Handler(TcpClient client)
{
using (NetworkStream stream = client.GetStream())
{
var dataBuffer = new Byte[256];
int i;
while ((i = stream.Read(dataBuffer, 0, dataBuffer.Length)) != 0)
{
// Processes data here..
//var s = Encoding.UTF8.GetString(dataBuffer, 0, i);
//Console.Write(s);
}
}
}
关于c# - TcpListener/TcpClient 在某些情况下停止处理数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13404803/
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_