我正在开发一个服务器应用程序,它将接收消息并做出响应。没什么新鲜的。所以,实际上我关注this answer和this post,但我无法使AcceptAsync()
方法触发Completed
事件。在互联网上随处搜索,尝试了类似问题的解决方案,但似乎没有什么对我有用。
我还尝试从server.Start()
拨打Task.Run()
,但没有运气。我知道服务器听起来很好,因为我可以在netstat -an
上看到它,如果我在Listen()
之后中断,我还可以使用telnet进行连接。
根据我的理解,如果AcceptAsync()
方法返回true,它会引发SocketAsyncEventArgs.Completed
事件,而事件又将再次调用StartAccept()
方法并将循环直到我强行退出。
SocketAsyncEventArgs.Completed
也是正确的:http://prntscr.com/8l3x8p,但仍然无效。
这是我的代码:
public class TTSServer
{
private Socket m_serverSocket;
private IPEndPoint m_serverEndPoint;
[DefaultValue(39454)]
public int Port { get; set; }
[DefaultValue(100)]
public int IncommingQueueSize { get; set; }
[DefaultValue(512)]
public int BufferSize { get; set; }
//Listeners to hold event when something happens.
public static void Main(string[] args)
{
TTSServer server = new TTSServer(39454, 100, 512);
server.Start();
}
public TTSServer(int port, int queueSize, int bufferSize)
{
Port = port;
IncommingQueueSize = queueSize;
BufferSize = bufferSize;
}
public void Start()
{
Console.WriteLine("Starting TTS Server (Port: {0}, QueueSize: {1}, BufferSize: {2})", Port, IncommingQueueSize, BufferSize);
m_serverEndPoint = new IPEndPoint(IPAddress.Any, Port);
m_serverSocket = new Socket(m_serverEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine("Binding ({0})", m_serverEndPoint.ToString());
m_serverSocket.Bind(m_serverEndPoint);
Console.WriteLine("Listening");
m_serverSocket.Listen(IncommingQueueSize);
StartAccept(null);
}
public void Stop()
{
}
/// <summary>
/// Receive a incomming connection attemp in an asynchronous way.
/// </summary>
/// <param name="socketEvent">If is null, a new object is created, else, it'll be used for cache friendly reason.</param>
private void StartAccept(SocketAsyncEventArgs socketEvent)
{
//If received reference points to null, let's create a new object.
if (socketEvent == null)
{
Console.WriteLine("Accepting new connections...");
socketEvent = new SocketAsyncEventArgs();
socketEvent.Completed += AcceptCompleted; //Add a callback on completed accept incomming connections attemp.
}
else
{
//Clear current incomming connection socket, so object may be reused.
socketEvent.AcceptSocket = null;
}
//If there is an incomming connection pending(pooled), this method will receive the connection in a async way (witch returns true)
//and will call SocketAsyncEventArgs.Completed callback when done.
//Else, it waits for a new connection, returns false, and don't won't SocketAsyncEventArgs.Completed callback when done, so we have to
//call it manually.
bool async = true;
//When I debug this code, async receive true from AcceptAsync.
async = m_serverSocket.AcceptAsync(socketEvent);
if (!async)
{
AcceptCompleted(this, socketEvent);
}
}
/// <summary>
/// Handles a incomming connection after it's fully received. This function will do the business logic for incomming connections and prepare
/// to receive data.
/// </summary>
/// <param name="sender">Object who posted this function</param>
/// <param name="socketEvent">Information of the incomming connection</param>
private void AcceptCompleted(object sender, SocketAsyncEventArgs socketEvent)
{
Connection connection = new Connection(this, socketEvent.AcceptSocket, BufferSize);
SocketAsyncEventArgs connectedSocketEvent = new SocketAsyncEventArgs();
connectedSocketEvent.UserToken = connection;
//Add a receive callback, to be called whenever the Receive function is finished.
connectedSocketEvent.Completed += FlushBuffer;
ReceiveData(connectedSocketEvent);
//Accept next incomming connection.
StartAccept(socketEvent);
}
不知道为什么,AcceptCompleted
永远不会被解雇,即使AcceptAsync()
方法返回true
。
答案 0 :(得分:1)
似乎根本原因是默认缓冲:
可选地,可以提供缓冲区,其中在
ConnectAsync
方法成功之后在套接字上接收初始数据块。在这种情况下,需要将SocketAsyncEventArgs.Buffer
属性设置为包含要接收的数据的缓冲区,并且需要将SocketAsyncEventArgs.Count
属性设置为缓冲区中要接收的最大数据字节数。可以使用SocketAsyncEventArgs.SetBuffer
方法设置这些属性。传入的部分缓冲区将在内部使用,供底层WinsockAcceptEx
调用使用。这意味着返回的数据量始终小于提供的SocketAsyncEventArgs.Count
实例上的System.Net.Sockets.SocketAsyncEventArgs
属性值。内部使用的缓冲区数量取决于套接字的地址族。所需的最小缓冲区大小为288个字节。如果指定了更大的缓冲区大小,则Socket
将期望除WinsockAcceptEx
调用接收的地址数据之外的一些额外数据,并将等待直到收到此额外数据。如果发生超时,则重置连接。因此,如果预期额外数据具有特定数量,则应将缓冲区大小设置为最小缓冲区大小加上此数量。
假设不需要缓冲,请禁用缓冲seems to be a solution:
SocketAsyncEventArgs args = ...;
args.SetBuffer(null, 0, 0);
答案 1 :(得分:-1)
编辑:在示例中的server.Start之后添加一行阻塞代码。
你会想到改变一条线。
更改此
!SESSION 2015-09-27 21:25:19.484 -----------------------------------------------
eclipse.buildId=4.5.0.I20150603-2000
java.version=1.8.0_60
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86, WS=win32, NL=en_US
Framework arguments: -product org.eclipse.epp.package.java.product -product org.eclipse.epp.package.java.product
Command-line arguments: -os win32 -ws win32 -arch x86 -product org.eclipse.epp.package.java.product -data d:\workspace -product org.eclipse.epp.package.java.product
This is a continuation of log file D:\workspace\.metadata\.bak_0.log
Created Time: 2015-09-27 21:28:00.484
!ENTRY org.eclipse.core.resources 4 2 2015-09-27 21:28:00.484
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.core.resources".
!STACK 0
java.lang.NoClassDefFoundError: org/eclipse/mtj/internal/core/util/Utils
at org.eclipse.mtj.internal.core.util.MTJBuildPropertiesResourceListener.filterResourceDeltas(MTJBuildPropertiesResourceListener.java:169)
at org.eclipse.mtj.internal.core.util.MTJBuildPropertiesResourceListener.resourceChanged(MTJBuildPropertiesResourceListener.java:91)
at org.eclipse.core.internal.events.NotificationManager$1.run(NotificationManager.java:299)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.NotificationManager.notify(NotificationManager.java:289)
at org.eclipse.core.internal.events.NotificationManager.broadcastChanges(NotificationManager.java:152)
at org.eclipse.core.internal.resources.Workspace.broadcastPostChange(Workspace.java:373)
at org.eclipse.core.internal.resources.Workspace.endOperation(Workspace.java:1470)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2250)
at org.eclipse.core.internal.events.NotificationManager$NotifyJob.run(NotificationManager.java:43)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
!ENTRY org.eclipse.core.resources 4 2 2015-09-27 21:28:00.500
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.core.resources".
!STACK 0
java.lang.NoClassDefFoundError: org/eclipse/mtj/internal/core/util/ClasspathChangeMonitor$ClassPathVisitor
at org.eclipse.mtj.internal.core.util.ClasspathChangeMonitor.resourceChanged(ClasspathChangeMonitor.java:97)
at org.eclipse.core.internal.events.NotificationManager$1.run(NotificationManager.java:299)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.NotificationManager.notify(NotificationManager.java:289)
at org.eclipse.core.internal.events.NotificationManager.broadcastChanges(NotificationManager.java:152)
at org.eclipse.core.internal.resources.Workspace.broadcastPostChange(Workspace.java:373)
at org.eclipse.core.internal.resources.Workspace.endOperation(Workspace.java:1470)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2250)
at org.eclipse.core.internal.events.NotificationManager$NotifyJob.run(NotificationManager.java:43)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
!ENTRY org.eclipse.jdt.core 4 2 2015-09-27 21:28:00.781
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.jdt.core".
!STACK 1
org.eclipse.core.runtime.CoreException: Plug-in org.eclipse.mtj.core was unable to load class org.eclipse.mtj.internal.core.build.MTJCompilationParticipant.
at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.throwException(RegistryStrategyOSGI.java:194)
at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:176)
at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:905)
at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:243)
at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:55)
at org.eclipse.jdt.internal.core.JavaModelManager$CompilationParticipants$1.run(JavaModelManager.java:344)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.jdt.internal.core.JavaModelManager$CompilationParticipants.getCompilationParticipants(JavaModelManager.java:339)
at org.eclipse.jdt.internal.core.builder.JavaBuilder.initializeBuilder(JavaBuilder.java:589)
at org.eclipse.jdt.internal.core.builder.JavaBuilder.build(JavaBuilder.java:169)
at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:734)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:205)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:245)
at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:300)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:303)
at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:359)
at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:382)
at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:144)
at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:235)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
Caused by: java.lang.ClassNotFoundException: An error occurred while automatically activating bundle org.eclipse.mtj.core (587).
at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:116)
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:531)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:324)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:327)
at org.eclipse.osgi.internal.loader.sources.SingleSourcePackage.loadClass(SingleSourcePackage.java:36)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:398)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:352)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:344)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:160)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at org.eclipse.osgi.internal.framework.BundleContextImpl.loadBundleActivator(BundleContextImpl.java:755)
at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:706)
at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:941)
at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:318)
at org.eclipse.osgi.container.Module.doStart(Module.java:571)
at org.eclipse.osgi.container.Module.start(Module.java:439)
at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:454)
at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:531)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:324)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:327)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:402)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:352)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:344)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:160)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:573)
at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:174)
at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:905)
at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:243)
at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:55)
at org.eclipse.ui.internal.WorkbenchPlugin$1.run(WorkbenchPlugin.java:293)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.ui.internal.WorkbenchPlugin.createExtension(WorkbenchPlugin.java:288)
at org.eclipse.ui.internal.dialogs.WorkbenchPreferenceNode.createPage(WorkbenchPreferenceNode.java:48)
at org.eclipse.jface.preference.PreferenceDialog.createPage(PreferenceDialog.java:1300)
at org.eclipse.ui.internal.dialogs.FilteredPreferenceDialog.createPage(FilteredPreferenceDialog.java:355)
at org.eclipse.jface.preference.PreferenceDialog.showPage(PreferenceDialog.java:1187)
at org.eclipse.ui.internal.dialogs.FilteredPreferenceDialog.showPage(FilteredPreferenceDialog.java:608)
at org.eclipse.jface.preference.PreferenceDialog$9$1.run(PreferenceDialog.java:675)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.jface.preference.PreferenceDialog$9.selectionChanged(PreferenceDialog.java:670)
at org.eclipse.jface.viewers.StructuredViewer$3.run(StructuredViewer.java:877)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:50)
at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:173)
at org.eclipse.jface.viewers.StructuredViewer.firePostSelectionChanged(StructuredViewer.java:874)
at org.eclipse.jface.viewers.StructuredViewer.handlePostSelect(StructuredViewer.java:1243)
at org.eclipse.jface.viewers.StructuredViewer$5.widgetSelected(StructuredViewer.java:1269)
at org.eclipse.jface.util.OpenStrategy.firePostSelectionEvent(OpenStrategy.java:265)
at org.eclipse.jface.util.OpenStrategy.access$5(OpenStrategy.java:259)
at org.eclipse.jface.util.OpenStrategy$1$2.run(OpenStrategy.java:440)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4155)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3772)
at org.eclipse.jface.window.Window.runEventLoop(Window.java:827)
at org.eclipse.jface.window.Window.open(Window.java:803)
at org.eclipse.ui.internal.dialogs.WorkbenchPreferenceDialog.open(WorkbenchPreferenceDialog.java:211)
at org.eclipse.ui.internal.OpenPreferencesAction.run(OpenPreferencesAction.java:63)
at org.eclipse.jface.action.Action.runWithEvent(Action.java:473)
at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:595)
at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:511)
at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:420)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4362)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1113)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4180)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3769)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$4.run(PartRenderingEngine.java:1127)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1018)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:156)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:654)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:598)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:139)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:669)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:608)
at org.eclipse.equinox.launcher.Main.run(Main.java:1515)
Caused by: org.osgi.framework.BundleException: Exception in org.eclipse.mtj.core.MTJCore.start() of bundle org.eclipse.mtj.core.
at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:792)
at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:721)
at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:941)
at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:318)
at org.eclipse.osgi.container.Module.doStart(Module.java:571)
at org.eclipse.osgi.container.Module.start(Module.java:439)
at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:454)
at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)
... 93 more
Caused by: java.lang.NoClassDefFoundError: org/eclipse/osgi/framework/debug/FrameworkDebugOptions
at org.eclipse.mtj.internal.core.hooks.Debug.(Debug.java:31)
at org.eclipse.mtj.internal.core.hook.sourceMapper.SourceMapperAccess.setSourceMapper(SourceMapperAccess.java:72)
at org.eclipse.mtj.core.MTJCore.start(MTJCore.java:490)
at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:771)
at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:764)
... 100 more
Caused by: java.lang.ClassNotFoundException: org.eclipse.osgi.framework.debug.FrameworkDebugOptions cannot be found by org.eclipse.mtj.core.hooks_1.0.0.201101310801
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:439)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:352)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:344)
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:160)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 107 more
到此
socketEvent.Completed += AcceptCompleted; //Add a callback on completed accept incomming connections attemp.