关于 IOCP 整合 SSL 的一个帖子

原文:http://marc.info/?l=openssl-users&m=99909952822335&w=2

 

感觉这方面的资料非常少,这是能找到的比较有用的资源之一了.

 

[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openssl-users
Subject:    RE: OpenSSL and Winsock IO Completion Ports
From:       "Dale Peakall" <dale.peakall () bit-arts ! com>
Date:       2001-08-29 15:36:59
[Download message RAW]

> I am a bit new to OpenSSL, and I am  a C++ Programmer.
> I'm trying to develop a server that will use the OpenSSL library, under
> the mechanism of Winsock's I/O Com[pletion Ports(IOCP).
> Would someone please tell me how is it possible?

The normal solution is to make use of the SSL libraries BIO mechanism.
A BIO represents an I/O stream and all data read/written by the SSL library
uses a BIO.  When you call SSL_set_fd(), the SSL library internally
creates a pair of BIO's that know how to read and write from a socket.

You can make the SSL library read/write from a different type of BIO by
using the SSL_set_bio() function.

The type of BIO you want to use is created by calling BIO_new_bio_pair().

BIO_new_bio_pair() returns a pair of BIO's that are linked.  One of the
BIO's (generally called the 'internal' BIO) is used for reading/writing
unencrypted data, the other (generally called the 'network' BIO) is used
for reading/writing encrypted data.

The BIO's are linked so that data written to the internal BIO appears
encrypted on the network BIO and data written to the network BIO appears
unencrypted on the internal BIO.

A good place to look for example code is Lutz Jaenicke's Postfix/TLS
toolkit.

http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/

> I mean, the OpenSSL's read() and write() methods are only for plain send
and recieve. Moreover, > to use the IOCP mechanism I need to use Overlapped
IO, so how can I do this combining OpenSSL?
> If there's an example I would like to have it.

There's a lot of work involved in this, you basically need to have a pool of
threads that wait on GetQueuedCompletionStatus().  When data is received
they need to write it onto the network BIO.

If the data is part of the SSL/TLS handshake (you can tell by calling
SSL_in_init()) you need to call SSL_accept() or SSL_connect() depending
on whether you're a client or a server.

Otherwise, you need to call your application level handlers that try to read
the data from the internal BIO and do whatever is appropriate.

Having done this, you need to determine whether there's data to be written
(you can tell be calling BIO_ctrl_pending() on the network BIO) and post an
OVERLAPPED write request.

Don't forget to post another OVERLAPPED read request and off you go.

In addition, if you're acting as a server you'll need to handle accepting
new
connections (with WSAAsyncAccept()) etc.

It all gets pretty complex, pretty quick, but it is manageable.  It took me
about three months development to write a basic server that does everything
without leaking, crashing or running into a loop (that's without application
code - apart from the message dispatcher).

> Another thing: I would like to know how to properly build and configure a
> certificate into the SSL Program.

You can create the appropriate C structures from a certificate using the
openssl x509 -C -noout -in <file> command (or something like that - the -C
flag is the important one).

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majordomo@openssl.org

[prev in list] [next in list] [prev in thread] [next in thread] 


Configure | About | News | Donate | Add a list | Sponsors: 10EastKoreLogicChakpak.com

 

 

2011.06.14

其实,在他们的组里,还是有很多的相关资料的。不过,好像问个问题能得到回复总是比较难!

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IOCP(Input/Output Completion Port)是一种高效的异步I/O模型,可用于实现高性能的服务器。在Windows系统中,可以使用IOCP API来创建一个IOCP服务器。 下面是一个简单的IOCP服务器的示例代码: ```c #include <stdio.h> #include <winsock2.h> #include <windows.h> #define PORT 12345 #define MAX_CLIENTS 10 #define BUFFER_SIZE 1024 typedef struct { OVERLAPPED overlapped; SOCKET socket; WSABUF wsaBuf; CHAR buffer[BUFFER_SIZE]; DWORD bytesTransferred; DWORD flags; } PER_IO_DATA, *LPPER_IO_DATA; VOID CALLBACK CompletionRoutine(DWORD dwErrorCode, DWORD dwBytesTransfered, LPOVERLAPPED lpOverlapped, DWORD dwFlags); int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); // 创建监听套接字 SOCKET listenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (listenSocket == INVALID_SOCKET) { printf("Error creating listen socket: %d\n", WSAGetLastError()); return 1; } // 绑定端口号 SOCKADDR_IN serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(PORT); if (bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { printf("Error binding port: %d\n", WSAGetLastError()); return 1; } // 监听连接 if (listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) { printf("Error listening: %d\n", WSAGetLastError()); return 1; } // 创建IOCP句柄 HANDLE iocpHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (iocpHandle == NULL) { printf("Error creating IOCP handle: %d\n", GetLastError()); return 1; } // 将监听套接字绑定到IOCP句柄上 if (CreateIoCompletionPort((HANDLE)listenSocket, iocpHandle, (ULONG_PTR)listenSocket, 0) == NULL) { printf("Error binding listen socket to IOCP handle: %d\n", GetLastError()); return 1; } // 创建客户端套接字 SOCKET clientSockets[MAX_CLIENTS]; for (int i = 0; i < MAX_CLIENTS; i++) { clientSockets[i] = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (clientSockets[i] == INVALID_SOCKET) { printf("Error creating client socket: %d\n", WSAGetLastError()); return 1; } } // 接受连接 for (;;) { SOCKADDR_IN clientAddr; int clientAddrLen = sizeof(clientAddr); SOCKET clientSocket = accept(listenSocket, (SOCKADDR*)&clientAddr, &clientAddrLen); if (clientSocket == INVALID_SOCKET) { printf("Error accepting connection: %d\n", WSAGetLastError()); continue; } // 将客户端套接字绑定到IOCP句柄上 if (CreateIoCompletionPort((HANDLE)clientSocket, iocpHandle, (ULONG_PTR)clientSocket, 0) == NULL) { printf("Error binding client socket to IOCP handle: %d\n", GetLastError()); closesocket(clientSocket); continue; } // 分配PER_IO_DATA结构体 LPPER_IO_DATA perIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA)); perIoData->socket = clientSocket; perIoData->wsaBuf.buf = perIoData->buffer; perIoData->wsaBuf.len = BUFFER_SIZE; perIoData->flags = 0; // 开始接收数据 DWORD bytesRecv; if (WSARecv(clientSocket, &perIoData->wsaBuf, 1, &bytesRecv, &perIoData->flags, &perIoData->overlapped, CompletionRoutine) == SOCKET_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("Error starting receive: %d\n", WSAGetLastError()); GlobalFree(perIoData); closesocket(clientSocket); continue; } } } // 关闭监听套接字 closesocket(listenSocket); // 释放资源 for (int i = 0; i < MAX_CLIENTS; i++) { closesocket(clientSockets[i]); } WSACleanup(); return 0; } VOID CALLBACK CompletionRoutine(DWORD dwErrorCode, DWORD dwBytesTransfered, LPOVERLAPPED lpOverlapped, DWORD dwFlags) { LPPER_IO_DATA perIoData = (LPPER_IO_DATA)lpOverlapped; if (dwErrorCode == 0 && dwBytesTransfered > 0) { printf("Received %d bytes from socket %d\n", dwBytesTransfered, perIoData->socket); } else { printf("Error receiving data: %d\n", dwErrorCode); } GlobalFree(perIoData); closesocket(perIoData->socket); } ``` 在这个示例中,我们首先创建一个监听套接字,绑定端口号并开始监听连接。然后,我们创建一个IOCP句柄,并将监听套接字绑定到IOCP句柄上。 接下来,我们创建一些客户端套接字,并在接受连接时将它们绑定到IOCP句柄上。每当有一个客户端连接到服务器时,我们为其分配一个PER_IO_DATA结构体,并使用WSARecv函数开始接收数据。在WSARecv函数中,我们将PER_IO_DATA结构体的地址传递给了overlapped参数,这样就可以在数据接收完成后得到它。 当数据接收完成后,系统会调用CompletionRoutine回调函数。在这个函数中,我们可以检查数据接收是否成功,并释放PER_IO_DATA结构体和客户端套接字。 需要注意的是,在IOCP服务器中,所有的I/O操作都是异步的,因此我们需要使用OVERLAPPED结构体来描述每一个I/O操作,并在每个I/O操作完成后启动回调函数。在这个示例中,我们使用了PER_IO_DATA结构体来扩展OVERLAPPED结构体,并包含了一些额外的信息,例如套接字、接收缓冲区等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值