Winsock completion port Model-delphi code

Source: Internet
Author: User

The original source "Windows network Programming Technology" The 8th chapter completes the Port model

Since the original book is attached to the C code, I translate it into Delphi code.

Where Winsock2.pas in the Delphi without, to download the additional Http://jungla.dit.upm.es/~bti/files/winsock2.pas

Program Completionio;

{$APPTYPE CONSOLE}

Uses
Sysutils,
WinSock2 in ' Winsock2.pas ',
Mains in ' Mains.pas ';

Begin
Main ();
End.

Module Name:iocmplt.cpp
//
Description:
//
This is sample illustrates how to develop a simple echo server Winsock
Application using the Completeion port I/O model. This
Sample is implemented as a Console-style application and simply prints
Messages when connections is established and removed from the server.
The application listens for TCP connections on port 5150 and accepts them
As they arrive. When this application receives data from a client, it
Simply Echos (This is why we call it a echo server) the data back in
It ' s original form until the client closes the connection.
//
2005-2-5
CPP convert to Delphi pas by Johnson
//

Unit Mains;

Interface

Uses Windows, WinSock2, WinSock, sysutils;

Const
PORT = 5150;
Data_bufsize = 8192;


Type
LPVOID = Pointer;
Lpper_io_operation_data = ^ Per_io_operation_data;
Per_io_operation_data = Packed record
overlapped:overlapped;
Databuf:twsabuf;
Buffer:array [0..data_bufsize] of CHAR;
Bytessend:dword;
Bytesrecv:dword;
End

Lpper_handle_data = ^ Per_handle_data;
Per_handle_data = Packed record
Socket:tsocket;
End

Procedure main;

Implementation

function Serverworkerthread (completionportid:lpvoid): DWORD; stdcall; Forward

Procedure printf (fmt:string; num:integer);
Begin
Writeln (Format (FMT, [num]));
End

Procedure main;
Var
internetaddr:sockaddr_in;
Listen:tsocket;
Accept:tsocket;
Completionport:thandle;
Systeminfo:system_info;
Perhandledata:lpper_handle_data;
Periodata:lpper_io_operation_data;
I:integer;
Recvbytes:dword;
Flags:dword;
Threadid:dword;
Wsadata:twsadata;
Ret:dword;

Threadhandle:thandle;
Begin
Ret: = WSAStartup ($0202, wsadata);
if (Ret <> 0) Then
Begin
printf (' WSAStartup failed with error%d ', Ret);
Exit;
End

Setup an I/O completion port.
Completionport: = CreateIoCompletionPort (invalid_handle_value, 0, 0, 0);
if (completionport = 0) Then
Begin
printf (' CreateIoCompletionPort failed with error:%d ', GetLastError ());
Exit;
End


Determine how many processors is on the system.

GetSystemInfo (SystemInfo);

Create worker threads based on the number of processors available on the
System. Create the worker threads for each processor.

For i:= 0 to Systeminfo.dwnumberofprocessors * 2-1 do
Begin

Create a server worker thread and pass the completion port to the thread.
Threadhandle: = CreateThread (nil, 0, @ServerWorkerThread, Pointer (Completionport),
0, ThreadID);
if (threadhandle = 0) Then
Begin
printf (' CreateThread () failed with error%d ', GetLastError ());
Exit;
End

Close the thread handle
CloseHandle (Threadhandle);
End

Create a listening socket
Listen: = WSASocket (af_inet, sock_stream, 0, nil, 0, wsa_flag_overlapped);
if (Listen = invalid_socket) Then
Begin
printf (' WSASocket () failed with error%d ', WSAGetLastError ());
Exit
End

internetaddr.sin_family: = af_inet;
INTERNETADDR.SIN_ADDR.S_ADDR: = htonl (Inaddr_any);
Internetaddr.sin_port: = htons (port);

if (Bind (Listen, internetaddr, sizeof (INTERNETADDR)) = Socket_error) Then
Begin
printf (' Bind () failed with error%d ', WSAGetLastError ());
Exit
End

Prepare socket for listening

if (Winsock.listen (listen, 5) = Socket_error) Then
Begin
printf (' Listen () failed with error%d ', WSAGetLastError ());
Exit
End
Else
Begin
printf (' Server listen on port =%d ... ', port);
End


Accept connections and assign to the completion port.
while (TRUE) does
Begin
Accept: = Wsaaccept (Listen, nil, nil, nil, 0);
if (Accept = socket_error) Then
Begin
printf (' Wsaaccept () failed with error%d ', WSAGetLastError ());
Exit
End

Create A socket information structure to associate with the socket
Perhandledata: = Lpper_handle_data (GlobalAlloc (gptr, sizeof (Per_handle_data)));
if (Perhandledata = nil) Then
Begin
printf (' GlobalAlloc () failed with error%d ', WSAGetLastError ());
Exit
End

Associate the accepted socket with the original completion port.

printf (' Socket number%d connected ', Accept);
Perhandledata.socket: = Accept;

if (CreateIoCompletionPort (Accept, Completionport, DWORD (Perhandledata), 0) = 0) Then
Begin
printf (' CreateIoCompletionPort () failed with error%d ', WSAGetLastError ());
Exit
End

Create per I/O socket information structure to associate with the
WSARecv call below.

Periodata: = Lpper_io_operation_data (GlobalAlloc (gptr, sizeof (Per_io_operation_data)));
if (Periodata = nil) Then
Begin
printf (' GlobalAlloc () failed with error%d ', WSAGetLastError ());
Exit
End

      ZeroMemory (@PerIoData. Overlapped, sizeof (Overlapped));
      Periodata.bytessend: = 0;
      Periodata.bytesrecv: = 0;
      PerIoData.DataBuf.len: = data_bufsize;
      PerIoData.DataBuf.buf: = @PerIoData. Buffer;

Flags: = 0;
if (WSARecv (Accept, @ (PERIODATA.DATABUF), 1, @RecvBytes, @Flags,
@ (periodata.overlapped), nil) = Socket_error) Then
Begin
if (WSAGetLastError () <> error_io_pending) Then
Begin
printf (' WSARecv () failed with error%d ', WSAGetLastError ());
Exit
End
End

End
End


function Serverworkerthread (completionportid:lpvoid): DWORD; stdcall;
Var
Completionport:thandle;
Bytestransferred:dword;
overlapped:poverlapped;
Perhandledata:lpper_handle_data;
Periodata:lpper_io_operation_data;
Sendbytes, Recvbytes:dword;
Flags:dword;
Begin
Completionport: = Thandle (Completionportid);

result:= 0;

while (TRUE) does
Begin

if (GetQueuedCompletionStatus (Completionport, bytestransferred,
DWORD (Perhandledata), poverlapped (Periodata), INFINITE) = False) Then
Begin
printf (' GetQueuedCompletionStatus failed with error%d ', GetLastError ());
Exit
End

First check to see if an error have occured on the socket and if so
Then close the socket and cleanup the socket_information structure
associated with the socket.

if (bytestransferred = 0) Then
Begin
printf (' Closing socket%d\ ', perhandledata.socket);

if (closesocket (perhandledata.socket) = Socket_error) Then
Begin
printf (' Closesocket () failed with error%d ', WSAGetLastError ());
Exit
End

GlobalFree (DWORD (perhandledata));
GlobalFree (DWORD (periodata));
Continue
End

Check to see if the Bytesrecv field equals zero. If this was so and then
This means a wsarecv call just completed so update the BYTESRECV field
With the bytestransferred value from the completed WSARecv ().

if (periodata.bytesrecv = 0) Then
Begin
PERIODATA.BYTESRECV: = bytestransferred;
Periodata.bytessend: = 0;
End
Else
Begin
Periodata.bytessend: = Periodata.bytessend + bytestransferred;
End

if (Periodata.bytesrecv > Periodata.bytessend) Then
Begin

Post another WSASend () request.
Since WSASend () is not gauranteed to send all of the bytes requested,
Continue posting WSASend () calls until all received bytes is sent.

ZeroMemory (@ (periodata.overlapped), sizeof (Overlapped));

PerIoData.DataBuf.buf: = Periodata.buffer + periodata.bytessend;
PerIoData.DataBuf.len: = Periodata.bytesrecv-periodata.bytessend;

if (WSASend (Perhandledata.socket, @ (PERIODATA.DATABUF), 1, @SendBytes, 0,
@ (periodata.overlapped), nil) = Socket_error) Then
Begin
if (WSAGetLastError () <> error_io_pending) Then
Begin
printf (' WSASend () failed with error%d ', WSAGetLastError ());
Exit;
End
End
End
Else
Begin
PERIODATA.BYTESRECV: = 0;

Now that there is no more bytes to send post another WSARECV () request.

Flags: = 0;
ZeroMemory (@ (periodata.overlapped), sizeof (Overlapped));

PerIoData.DataBuf.len: = data_bufsize;
PerIoData.DataBuf.buf: = @PerIoData. Buffer;

if (WSARecv (Perhandledata.socket, @ (PERIODATA.DATABUF), 1, @RecvBytes, @Flags,
@ (periodata.overlapped), nil) = Socket_error) Then
Begin
if (WSAGetLastError () <> error_io_pending) Then
Begin
printf (' WSARecv () failed with error%d ', WSAGetLastError ());
Exit
End
End
End
End
End


End.

Http://www.cnblogs.com/qiubole/archive/2006/04/06/368296.html

Winsock completion port Model-delphi code

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.