Function WSAConnect Winsockpas

Syntax

WSAConnect(s: TSocket; name: PSockAddr; namelen: Integer; IpCallerData: LPWSABUF; lpCalleeData: LPWSABUF; lpSQOS: LPQOS; lpGQOS: LPQOS): Integer; stdcall;

Description

The WSAConnect() function establishes a connection to another socket application, exchanges connect data, and specifies needed Quality of Service based on the specified FLOWSPEC structure, which is not discussed here.

Parameters s: A descriptor identifying an unconnected socket name: The name of the peer to which the socket is to be connected namelen: The length of name lpCallerData: A pointer to the user data that is to be transferred to the peer during connection establishment lpCalleeData: A pointer to the user data that is to be transferred back from the peer during connection establishment lpSQOS: A pointer to the flow specs for socket s, one for each direction lpGQOS: Reserved for future use with socket groups. This is not implemented in Winsock 2.2.

Return Value

If the function succeeds, it will return a value of zero. Otherwise, it will return SOCKET_ERROR. To retrieve the specific error code, call the function WSAGetLastError(). Possible error codes are WSANOTINITIALISED, WSAENETDOWN, WSAEADDRINUSE, WSAEINTR, WSAEINPROGRESS, WSAEALREADY, WSAEADDRNOTAVAIL, WSAEAFNOSUPPORT, WSAECONNREFUSED, WSAEFAULT, WSAEINVAL, WSAEISCONN, WSAENETUNREACH, WSAENOBUFS, WSAENOTSOCK, WSAEOPNOT-SUPP, WSAEPROTONOSUPPORT, WSAETIMEDOUT, WSAEWOULD-BLOCK, and WSAEACCES.

See Appendix B for a detailed description of the error codes.

See Also accept, bind, connect, getsockname, getsockopt, select, socket, WSAAsyncSelect, WSAEventSelect

Example

Listing 5-3 (program EX53) provides an example of using a generic echo server with overlapped I/O.

Listing 5-3: A generic echo server that uses overlapped I/O with event notification program EX53;

{$APPTYPE CONSOLE}

uses SysUtils, Windows, WinSock2;

const

MaxEchoes = 10; DataBuffSize = 8192;

type

PSocketlnfo = PSocketInfo; TSocketlnfo = record

Overlapped : WSAOverlapped; skt : TSocket;

Buffer : array[0..DataBuffSize - 1] of char; DataBuffer : WSABuf; BytesSend, BytesRecv : DWORD;

end;

WSAData: TWSAData; DummyAddr,

HostAddr: TSockAddrIn;

sktListen, sktAccept: TSocket;

Size: Integer;

EventTotal,

Flags,

ThreadID,

RecvBytes: DWORD;

EventArray : array[0..WSA_MAXIMUM_WAIT_EVENTS - 1] of WSAEVENT; Socketlnfo : array[o..WSA_MAXIMUM_WAIT_EVENTS - l] of PSocketInfo; Res : Integer;

CriticalSection : TRTLCriticalSection;

procedure CleanUp(S : String); begin

WriteLn('Call to ' + S + ' failed with error: ' + SysErrorMessage(WSAGetLastError)); WSACleanUp; Halt; end;

function ProcessIO(lpParameter : Pointer) : DWORD; stdcall; var

BytesTransferred,

Flags,

Index,

RecvBytes, i: DWORD;

SktInfo: PSocketInfo; begin

EventArray[EventTotal] := WSAEVENT(lpParameter);

while TRUE do begin

Index := WSAWaitForMultipleEvents(EventTotal, @EventArray, FALSE, WSA_INFINITE, FALSE);

if Index = WSA_WAIT_FAILED then begin

WriteLn('Call to WSAWaitForMultipleEvents() failed with error: ' +

SysErrorMessage(WSAGetLastError)); Result := 0; Exit; end;

WSAResetEvent(EventArray[0]); continue;

end;

SktInfo := PSocketInfo(GlobalAlloc(GPTR, SizeOf(TSocketInfo))); SktInfo := SocketInfo[Index - WSA_WAIT_EVENT_0]; WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);

if (WSAGetOverlappedResult(SktInfo~.skt,@SktInfo~.Overlapped, BytesTransferred, FALSE, Flags) = FALSE) then if (BytesTransferred = 0) then begin

WriteLn(Format('Closing socket %d',[SktInfo~.skt])); if closesocket(SktInfo~.skt) = SOCKET_ERROR then begin

WriteLn(Format('Call to closesocket() failed with error: %s', [SysErrorMessage(WSAGetLastError)]));

end;

GlobalFree(Cardinal(SktInfo));

WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]); // Clean up SocketInfo & EventArray ...

EnterCriticalSection(CriticalSection); if Index - WSA_WAIT_EVENT_0 + 1 <> EventTotal then for i := Index - WSA_WAIT_EVENT_0 to EventTotal - 1 do begin

EventArray[i] := EventArray[i+1]; SocketInfo[i] := SocketInfo[i+1]; end;

dec(EventTotal);

LeaveCriticalSection(CriticalSection); continue; end;

// Check if the BytesRecv field = 0 ... if SktInfo~.BytesRecv = 0 then begin

SktInfo~.BytesRecv := BytesTransferred; SktInfo~.BytesSend := 0; end else begin

SktInfo~.BytesSend := SktInfo~.BytesSend + BytesTransferred; end;

if SktInfo~.BytesRecv > SktInfo~.BytesSend then begin

ZeroMemory(@SktInfo~.Overlapped, SizeOf(TOverlapped)); SktInfo~.Overlapped.hEvent := EventArray[Index - WSA_WAIT_EVENT_0]; SktInfo~.DataBuffer.buf := SktInfo~.Buffer + SktInfo~.BytesSend; SktInfo~.DataBuffer.len := SktInfo~.BytesRecv - SktInfo~.BytesSend; if WSASend(SktInfo~.skt, @SktInfo~.DataBuffer, 1, SktInfo~.BytesSend, 0, @SktInfo~.Overlapped, NIL) = SOCKET_ERROR then if WSAGetLastError <> ERROR_IO_PENDING then begin

WriteLn(Format('Call to WSASend() failed with error: %s',

[SysErrorMessage(WSAGetLastError)])); Result := 0; Exit; end end else begin

SktInfo~.BytesRecv := 0; // We have more no bytes of data to receive ... Flags := 0;

ZeroMemory(@SktInfo~.Overlapped, SizeOf(TOverlapped));

SktlnfcT.Overlapped.hEvent EventArray[Index - WSA_WAIT_EVENT_0]; SktInfo~.DataBuffer.len := DataBuffSize; SktInfo~.DataBuffer.buf := SktInfo~.Buffer;

if WSARecv(SktInfo~.skt,@SktInfo~.DataBuffer, 1, RecvBytes, Flags,

@SktInfo~.Overlapped, NIL) = SOCKET_ERROR then if WSAGetLastError <> ERROR_IO_PENDING then begin

WriteLn(Format('Call to WSARecv() failed with error: %s',

[SysErrorMessage(WSAGetLastError)])); Result := 0; Exit; end; end;

begin EventTotal := 0;

InitializeCriticalSection(CriticalSection); if WSAStartUp($0202, WSAData) = 0 then try sktListen := WSASocket(AF_INET, SOCK_STREAM, 0, NIL, 0, WSA_FLAG_OVERLAPPED); if sktListen = INVALID_SOCKET then CleanUp('WSASocket()'); HostAddr.sin_family := AF_INET; HostAddr.sin_port := htons(IPPORT_ECHO); HostAddr.sin_addr.S_addr := htonl(INADDR_ANY); Res := bind(sktListen, @HostAddr, SizeOf(HostAddr)); if Res = SOCKET_ERROR then CleanUp('bind()'); Res := listen(sktListen,5); if Res = SOCKET_ERROR then CleanUp('listen()'); // Create a socket for accepting connections ...

sktAccept := WSASocket(AF_INET, SOCK_STREAM, 0, NIL, 0, WSA_FLAG_OVERLAPPED); if sktAccept = INVALID_SOCKET then CleanUp('WSASocket()'); // Create an event object ... EventArray[0] := WSACreateEvent; if EventArray[0] = WSA_INVALID_EVENT then CleanUp('WSACreateEvent()');

if CreateThread(NIL, 0, @ProcessIO, NIL, 0, ThreadID) = 0{ NIL} then CleanUp('CreateThread()'); EventTotal := 1;

DummyAddr.sin_family := AF_INET; DummyAddr.sin_port := htons(IPPORT_ECHO); DummyAddr.sin_addr.S_addr := INADDR_ANY; Size := SizeOf(DummyAddr); EventTotal := 1; // Enter an infinite loop ... while TRUE do begin sktAccept := accept(sktListen, @DummyAddr, @Size); if sktAccept = INVALID_SOCKET then CleanUp('accept()'); EnterCriticalSection(CriticalSection); // Create a socket information structure to associate with the accepted socket ... SocketInfo[EventTotal] := PSocketInfo(GlobalAlloc(GPTR, SizeOf(TSocketInfo))); if SocketInfo[EventTotal] = NIL then CleanUp('GlobalAlloc()');

// Populate the SktInfo structure ...

SocketInfo[EventTotal]~.skt := sktAccept;

ZeroMemory(@SocketInfo[EventTotal]~.Overlapped, SizeOf(TOverlapped)); SocketInfo[EventTotal]~.BytesSend := 0; socketInfo[EventTotal]~.BytesRecv := 0; socketInfo[EventTotal]~.DataBuffer.len := DataBuffSize; SocketInfo[EventTotal]~.DataBuffer.buf := SocketInfo[EventTotal]~.Buffer; EventArray[EventTotal] := WSACreateEvent; if EventArray[EventTotal] = WSA_INVALID_EVENT then CleanUp('WSACreateEvent()'); SocketInfo[EventTotal]~.Overlapped.hEvent := EventArray[EventTotal]; // Post a WSARecv() request to begin receiving data on the socket ... Flags := 0;

Res := WSARecv(SocketInfo[EventTotal]~.skt,@SocketInfo[EventTotal]~.DataBuffer,

1, RecvBytes, Flags, @SocketInfo[EventTotal]~.Overlapped, NIL); if Res = SOCKET_ERROR then if WSAGetLastError <> ERROR_IO_PENDING then begin

inc(EventTotal);

LeaveCriticalSection(CriticalSection); // Signal the first event in the event array to tell the worker thread to service // an additional event in the event array ... if WSASetEvent(EventArray[0]) = FALSE then begin

end;// while ... finally WSACleanUp; end else WriteLn('Failed to load Winsock...'); end.

Was this article helpful?

0 0

Responses

  • delfina
    How to implement wsaconnect in winsock program?
    7 years ago

Post a comment