蛙蛙推荐:用winsock和iocp api打造一个echo server

蛙蛙推荐:用winsock和iocp api打造一个echo server
摘要:上次给大家演示了在c#里如何使用iocp的相关api,这次我们结合winsock和iocp来做一个实际的例子,就是一个回显服务器。本示例是根据《windows网络编程技术》里的一个c++例子改变而成,其中费了不少功夫,请教了不少人,在此表示感谢,希望大家也能从中有所收获,尤其是和非托管代码打交道方面。当然本文只是一个示例程序,还有好多需要考虑的地方,比如有的地方可能会造成句柄泄漏,内存泄漏等。

这里用到了一些技术点,比如平台调用、反射,多线程等,当然还有iocp和winsock的api,及GCHandle,SafeHandle,Marshal类的使用等,不过相当多的东西,我上篇帖子讲的都很细了,如果对winsock api不了解可以查阅MSDN。也没什么技术难点,说几个细节的地方吧。

1、.net自带的System.Threading.NativeOverlapped类型是完全按照win32的Overlapped结构实现的,因为我们在WSASend和WSAReceive的时候想要传递更多的数据,而不只是一个重叠结构,所以我自己定义了一个WaOverlapped,在原有结构的末尾加了一个指针,指向一个自定义类的GC句柄,这样在工作线程里就可以拿到自定义的单IO数据了,这个是我想了N种办法不行后的一个可行的办法。
2、注意GCHandle在取到数据后不用的话记着Free掉,否则就有可能造成内存泄漏。
3、如果调用WSASend或者WSAReceive返回6的话,多半是你准备的单IO数据不对,6表示无效的句柄。
4、如果传递给WSASend或者WSAReceive的Overlapped没pin住,会抛异常的,等不到GetLastWin32Error,所以用GCHandle.Alloc(PerIoData.Overlapped, GCHandleType.Pinned)把它pin住。
5、这个类还没有进行各方面的优化,其中的单IO数据,socket等都可以做成对象池来重用,Accept还可以替换成AcceptEx来用一个现成的Socket来接受新的连接,而不是自动创建一个新的,还有缓冲区可以做成环状的,关于性能方面的优化,下次有机会再给大家做实验。
完整代码如下,windows2008打开不安全代码进行编译,然后可以用telnet进行测试。

using System;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32.SafeHandles;

namespace WawaSocket.Net.Iocp
{
    
用IOCP和winsock api实现一个echo服务器

    
封装原生的socket对象

    
日志类

    
win32 structs

    
封装winsock和iocp的相关API原型

    
public class WawaIocpTest
    
{
        
public static void Main(String[] args)
        
{
            IocpTest.Run();
        }

    }

}


 

小结:希望通过这3篇帖子能加深大家对c#开发windows上的网络应用的了解。

posted @ 2008-07-15 00:19  蛙蛙王子  Views(3861)  Comments(26Edit  收藏  举报