如果您分析使用的简单客户端应用程序SocketAsyncEventArgs,您将注意到Thread并ExecutionContext分配.
分配的来源是SocketAsyncEventArgs.StartOperationCommon使用创建ExecutionContext的副本ExecutionContext.CreateCopy().
ExecutionContext.SuppressFlow似乎是抑制这种分配的好方法.但是,此方法本身将在新线程中运行时生成分配.
我该如何避免这些分配?
所以我在这里阅读我最喜欢的软件模式书之一(面向模式的软件架构 - 并发和网络对象的模式),特别是有关Proactor/Reactor异步IO模式的部分.我可以看到如何通过使用可选择的通道,我可以很容易地实现Reactor风格的异步IO机制(并且已经这样做了).但是,我无法看到如何使用非阻塞写入实现适当的Proactor机制.这是利用OS管理的非阻塞写入功能.
操作系统特定调用支持的功能,如win32下的GetQueuedCompletionStatus.
我确实看到Java 7通过异步完成处理程序为NIO带来了一些更新(这似乎是在正确的方向).话虽如此......鉴于缺乏对操作系统管理的异步操作(特别是异步写入)的统一跨平台支持,我假设这是一个不使用本机操作系统支持的quassy实现.
所以我的问题是,基于proactor的IO处理是否可以在Java中以这样的方式处理,以便用于特定场景; 并且,如果Java NIO确实支持基于proactor的IO处理(在Java 6或Java 7中),那么是否正在使用OS管理的异步IO支持(即来自OS的完成回调)?此外,如果实现纯粹是在VM中,则性能优势很小,使用主动事件处理只提供构建并发网络处理软件的不同(可能更简单)方式.
对于那些对主动事件处理感兴趣的人来说,这是一篇很好的文章,概述了优点/缺点以及与传统的每个连接线程和反应式IO模型的比较.
我最初在我的活动中实现了一个异步任务,它将数据发送到服务器.但是当我改变活动时,连接就丢失了.为了避免这种情况,我的方法是实现集中网络操作并将数据发送到服务器的服务,下面给出了该服务的代码
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class SocketService extends Service {
public static final String SERVERIP = ""; //your computer IP address should be written here
public static final int SERVERPORT = 5000;
PrintWriter out;
Socket socket;
InetAddress serverAddr;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("I am in Ibinder onBind method");
return myBinder;
}
private final IBinder …Run Code Online (Sandbox Code Playgroud) 我有一个异步UDP服务器类,其中一个套接字绑定在IPAddress.Any上,我想知道收到的数据包被发送到哪个IP地址(...或接收到).看来我不能只使用Socket.LocalEndPoint属性,因为它总是返回0.0.0.0(这是有意义的,因为它绑定到那个......).
以下是我目前使用的代码的有趣部分:
private Socket udpSock;
private byte[] buffer;
public void Starter(){
//Setup the socket and message buffer
udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpSock.Bind(new IPEndPoint(IPAddress.Any, 12345));
buffer = new byte[1024];
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
}
private void DoReceiveFrom(IAsyncResult iar){
//Get the received message.
Socket recvSock = (Socket)iar.AsyncState;
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
byte[] localMsg = new byte[msgLen]; …Run Code Online (Sandbox Code Playgroud) 我在nginx中看到这样的代码:
if(fcntl(ngx_processes[s].channel[0], F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK) == -1) {
...
if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
...
Run Code Online (Sandbox Code Playgroud)
谁能告诉我什么是之间的区别fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK)和ioctl(s, FIOASYNC, &on),不async和nonblocking一样的东西?
这两个库共享相似的哲学和类似的设计决策.但是这个流行的WSGI基准测试表明eventlet速度比慢gevent.是什么让他们的表现如此不同?
据我所知,它们之间的主要区别是:
gevent故意取决于和被耦合到libev(libevent先前)而eventlet定义独立反应器接口并实现使用特定的适配器select,epoll和它后面扭曲反应器中.额外的反应器接口是否会产生关键性能?
gevent主要用Cython编写,而eventlet用纯Python编写.本机编译Cython比纯Python更快,对于计算量不大但是IO绑定的程序?
的原语gevent仿效标准库接口而eventlet的基元从标准不同,并提供额外的层来模拟它.额外的仿真层是否会eventlet变慢?
执行eventlet.wsgi情况比刚好差gevent.pywsgi吗?
我真的很好奇,因为它们对我来说总体看起来很相似.
我正在通过内存分析器运行我的应用程序来检查泄漏.事情似乎有点好,但我得到了很多这些OverlappedData似乎在终结器队列中徘徊,几乎没有任何东西.它们是通过关闭NetworkStream连接两端的底层而取消的重叠IO的结果.
网络流本身被丢弃.没有NetworkStream任何地方的实时实例.
通常,他们根植于一些被称为OverlappedDataCacheLine.I'm调用EndRead在回调中我做的第一件事,所以没有调用BeginRead应该没有它的相应EndRead.
这是一个非常典型的外观,是谁从工具中保留它

最后它确实得到了GC,但它需要永远 - 大约半小时的时间来杀死一切,当我开始大约一千条流,把它们放入异步呼叫BeginRead并在大约一分钟后关闭它们.
该程序在端口80上对网络服务器稍微重现了这个问题.任何网络服务器都会真正做到.
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
class Program
{
static void Main(string[] args)
{
var clients = new List<TcpClient>();
for (int i = 0; i < 1000; ++i) {
var client = new TcpClient();
clients.Add(client);
client.BeginConnect("localhost", 80, connectResult =>
{
client.EndConnect(connectResult);
var stream = client.GetStream();
stream.BeginRead(new byte[1000], 0, 1000, result =>
{
try
{ …Run Code Online (Sandbox Code Playgroud) 我正在寻找我的网络层的改造.是否有任何方法可以判断特定异步请求是否在任何给定时刻运行?
例如,我想知道请求是否正在运行,以便我可以在不同时间更新用户界面.我可以通过保持变量跟踪状态来自己做这件事,但想知道库中是否已存在某些东西.
我应该声明我还没有询问具体的实现细节(但是),而只是概述了正在发生的事情.我理解套接字背后的基本概念,需要对整个过程进行澄清.我(可能是非常错误的)理解目前是这样的:
套接字不断监听想要连接的客户端(在自己的线程中).发生连接时,会引发一个事件,该事件会生成另一个线程以执行连接过程.在连接过程中,客户端被分配了自己的套接字,用于与服务器通信.然后,服务器等待来自客户端的数据,当数据到达时,会引发一个事件,该事件产生一个线程,将数据从流中读入缓冲区.
我的问题是:
我的理解有多少?
每个客户端套接字是否需要它自己的线程来监听数据?
如何将数据路由到正确的客户端套接字?这是TCP/UDP /内核的内容吗?
在这种线程环境中,通常会共享什么样的数据,争论的焦点是什么?
任何澄清和其他解释将不胜感激.
编辑:
关于通常共享什么数据和争用点的问题,我意识到这更像是一个实现细节,而不是关于接受连接和发送/接收数据的一般过程的问题.我查看了几个实现(SuperSocket和Kayak)并注意到会话缓存和可重用缓冲池之类的一些同步.随意忽略这个问题.我很感激您的反馈意见.
我正在尝试在模拟器上运行iPhone程序.我的问题是接收UDP数据.我使用asyncUdpSocket.如果我做一个插座并使用sendData:(NSData) toHost:,......好吧它工作正常.
想想我可能无法弄清楚接收功能是如何工作的.
我假设这样的事情:
socket = [[AsyncUdpSocket alloc] initWithDelegate:self];
[socket bindToPort:8000] error:nil] //returns YES
[socket receiveWithTimeout:-1 tag:1];
Run Code Online (Sandbox Code Playgroud)
我相信它应该调用该方法 -(BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long) fromHost:(NSString *)host port:(UInt16)port
好吧,我在该方法中放置了一个NSLog,它永远不会被调用.那么[socket receive,..]是唯一的接收方法,所以我想它应该是那个...或者是否有另一种方法我必须使用?或者我必须为我的代表或其他任何东西做一些补充......我只是无法弄清楚我是如何做到的
我搜索了asyncUdpSocket示例,教程,如何('s)等等,但我找不到一个例子.因此,如果有人想解释它或知道坐在一个很好的解释,将非常感激.
如果您还不知道答案,那么无论如何都要阅读!
asyncsocket ×10
sockets ×4
c# ×3
android ×2
udp ×2
allocation ×1
asynchronous ×1
c ×1
cocoa-touch ×1
eventlet ×1
gevent ×1
iphone ×1
java ×1
memory-leaks ×1
nio ×1
nonblocking ×1
performance ×1
retrofit ×1
tcp ×1
wsgi ×1