| Tenouk.com |< Winsock Program Example 4 | Main | Winsock Program Example 6 >| Site Index | Download |


 

WINSOCK 2

WINDOWS SOCKET: PROGRAM EXAMPLES PART 5

 

 

 

Winsock Tutorial

 

Winsock: Story 1

Winsock: Story 2

Winsock: Story 3

Winsock: Example 1

Winsock: Example 2

Winsock: Example 3

Winsock: Example 4

Winsock: Example 5

Winsock: Example 6

Winsock: Example 7

Winsock: Example 8

Winsock: Example 9

Winsock: Example 10

Winsock: Example 11

Winsock: Example 12

Winsock: Reference 1

Winsock: Reference 2

Winsock: Reference 3

Winsock: Reference 4

My Training Period:          hours

 

Note:

This is a continuation from previous Module.

Machine’s OS is standalone Windows Xp Pro with SP2 except whenever mentioned.  Compiler used was Visual C++ 2003 .Net 1.1. Beware the codes that span more than one line.  Program examples have been tested for Non Destructive Test :o).  All information compiled for Windows 2000 (NT5.0) above and...

 

  1. The story was discussed at Winsock introduction story.
  2. Related functions, structures and macros used in the program examples have been dumped at Winsock structure & function 1 and Winsock structure & function 2.
  3. Other related and required information (if any) not available in no. 2 can be found at MSDN & Visual C++ online reference.

 

Abilities

 

         Able to understand the basic of networking such as protocol, client, server and TCP/IP suite.

         Able to understand Winsock implementation and operations through the APIs and program examples.

         Able to gather, understand and use the Winsock functions, structures and macros in your programs.

         Able to build programs that use Microsoft C/Standard C programming language and Winsock APIs.

 

recv()

 

Item

Description

Function

recv().

Use

Receives data from a connected or bound socket.

Prototype

int recv(SOCKET s, char* buf, int len, int flags);

Parameters

s

[in] Descriptor identifying a connected socket.

 

buf

[out] Buffer for the incoming data.

 

len

[in] Length of buf, in bytes

 

flags

[in] Flag specifying the way in which the call is made.

Return value

See below.

Include file

<winsock2.h>

Library

ws2_32.lib

Remark

See below.

 

Table 1

 

Return Values

 

If no error occurs, recv() returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError().

 

Error code

Meaning

WSANOTINITIALISED

A successful WSAStartup() call must occur before using this function.

WSAENETDOWN

The network subsystem has failed.

WSAEFAULT

The buf parameter is not completely contained in a valid part of the user address space.

WSAENOTCONN

The socket is not connected.

WSAEINTR

The (blocking) call was canceled through WSACancelBlockingCall().

WSAEINPROGRESS

A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.

WSAENETRESET

The connection has been broken due to the keep-alive activity detecting a failure while the operation was in progress.

WSAENOTSOCK

The descriptor is not a socket.

WSAEOPNOTSUPP

MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations.

WSAESHUTDOWN

The socket has been shut down; it is not possible to receive on a socket after shutdown() has been invoked with how set to SD_RECEIVE or SD_BOTH.

WSAEWOULDBLOCK

The socket is marked as non-blocking and the receive operation would block.

WSAEMSGSIZE

The message was too large to fit into the specified buffer and was truncated.

WSAEINVAL

The socket has not been bound with bind(), or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled or (for byte stream sockets only) len was zero or negative.

WSAECONNABORTED

The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no longer usable.

WSAETIMEDOUT

The connection has been dropped because of a network failure or because the peer system failed to respond.

WSAECONNRESET

The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket as it is no longer usable. On a UDP-datagram socket this error would indicate that a previous send operation resulted in an ICMP "Port Unreachable" message.

 

Table 2

 

Remarks

 

The recv() function is used to read incoming data on connection-oriented sockets, or connectionless sockets. When using a connection-oriented protocol, the sockets must be connected before calling recv(). When using a connectionless protocol, the sockets must be bound before calling recv(). The local address of the socket must be known. For server applications, use an explicit bind() function or an implicit accept() or WSAAccept() function. Explicit binding is discouraged for client applications. For client applications, the socket can become bound implicitly to a local address using connect(), WSAConnect(), sendto(), WSASendTo(), or WSAJoinLeaf(). For connected or connectionless sockets, the recv() function restricts the addresses from which received messages are accepted. The function only returns messages from the remote address specified in the connection. Messages from other addresses are (silently) discarded.

 

 

 

For connection-oriented sockets (type SOCK_STREAM for example), calling recv() will return as much information as is currently available—up to the size of the buffer specified. If the socket has been configured for in-line reception of OOB data (socket option SO_OOBINLINE) and OOB data is yet unread, only OOB data will be returned. The application can use the ioctlsocket() or WSAIoctl() SIOCATMARK command to determine whether any more OOB data remains to be read.

For connectionless sockets (type SOCK_DGRAM or other message-oriented sockets), data is extracted from the first enqueued datagram (message) from the destination address specified by the connect() function. If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recv() generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost; for reliable protocols, the data is retained by the service provider until it is successfully read by calling recv() with a large enough buffer.

If no incoming data is available at the socket, the recv() call blocks and waits for data to arrive according to the blocking rules defined for WSARecv() with the MSG_PARTIAL flag not set unless the socket is non-blocking. In this case, a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select(), WSAAsyncSelect(), or WSAEventSelect() functions can be used to determine when more data arrives.

If the socket is connection oriented and the remote side has shut down the connection gracefully, and all data has been received, a recv() will complete immediately with zero bytes received. If the connection has been reset, a recv() will fail with the error WSAECONNRESET. The flags parameter can be used to influence the behavior of the function invocation beyond the options specified for the associated socket. The semantics of this function are determined by the socket options and the flags parameter. The latter is constructed by using the bitwise OR operator with any of the following values.

 

Value

Meaning

MSG_PEEK

Peeks at the incoming data. The data is copied into the buffer but is not removed from the input queue. The function subsequently returns the amount of data that can be read in a single call to the recv() (or recvfrom()) function, which may not be the same as the total amount of data queued on the socket. The amount of data that can actually be read in a single call to the recv() (or recvfrom()) function is limited to the data size written in the send() or sendto() function call.

MSG_OOB

Processes Out Of Band (OOB) data.

 

Table 3

 

Program Example

 

The following example demonstrates the use of the recv() function on server and client.

 

// Microsoft Development Environment 2003 - Version 7.1.3088

// Copyright (r) 1987-2002 Microsoft Corporation. All Right Reserved

// Microsoft .NET Framework 1.1 - Version 1.1.4322

// Copyright (r) 1998-2002 Microsoft Corporation. All Right Reserved

//

// Run on Windows XP Pro machine, version 2002, SP 2

//

// <windows.h> already included

// WINVER = 0x0501 for Xp already defined in windows.h

// Server program, using TCP

 

#include <stdio.h>

#include <winsock2.h>

 

int main()

{

WORD wVersionRequested;

WSADATA wsaData;

int wsaerr;

 

// Using MAKEWORD macro, Winsock version request 2.2

wVersionRequested = MAKEWORD(2, 2);

 

wsaerr = WSAStartup(wVersionRequested, &wsaData);

if (wsaerr != 0)

{

    /* Tell the user that we could not find a usable */

    /* WinSock DLL.*/

    printf("Server: The Winsock dll not found!\n");

    return 0;

}

else

{

       printf("Server: The Winsock dll found!\n");

       printf("Server: The status: %s.\n", wsaData.szSystemStatus);

}

 

/* Confirm that the WinSock DLL supports 2.2.*/

/* Note that if the DLL supports versions greater    */

/* than 2.2 in addition to 2.2, it will still return */

/* 2.2 in wVersion since that is the version we      */

/* requested.                                        */

if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )

{

    /* Tell the user that we could not find a usable */

    /* WinSock DLL.*/

    printf("Server: The dll do not support the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));

    WSACleanup();

    return 0;

}

else

{

       printf("Server: The dll supports the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));

       printf("Server: The highest version this dll can support: %u.%u\n", LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));

}

 

//////////Create a socket////////////////////////

//Create a SOCKET object called m_socket.

SOCKET m_socket;

 

// Call the socket function and return its value to the m_socket variable.

// For this application, use the Internet address family, streaming sockets, and

// the TCP/IP protocol.

// using AF_INET family, TCP socket type and protocol of the AF_INET - IPv4

m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

 

// Check for errors to ensure that the socket is a valid socket.

if (m_socket == INVALID_SOCKET)

{

    printf("Server: Error at socket(): %ld\n", WSAGetLastError());

    WSACleanup();

    return 0;

}

else

{

    printf("Server: socket() is OK!\n");

}

 

////////////////bind//////////////////////////////

// Create a sockaddr_in object and set its values.

sockaddr_in service;

 

// AF_INET is the Internet address family.

service.sin_family = AF_INET;

// "127.0.0.1" is the local IP address to which the socket will be bound.

service.sin_addr.s_addr = inet_addr("127.0.0.1");

// 55555 is the port number to which the socket will be bound.

service.sin_port = htons(55555);

 

// Call the bind function, passing the created socket and the sockaddr_in structure as parameters.

// Check for general errors.

if (bind(m_socket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)

{

    printf("Server: bind() failed: %ld.\n", WSAGetLastError());

    closesocket(m_socket);

    return 0;

}

else

{

    printf("Server: bind() is OK!\n");

}

 

// Call the listen function, passing the created socket and the maximum number of allowed

// connections to accept as parameters. Check for general errors.

if (listen(m_socket, 10) == SOCKET_ERROR)

   printf("Server: listen(): Error listening on socket %ld.\n", WSAGetLastError());

else

{

   printf("Server: listen() is OK, I'm waiting for connections...\n");

}

 

// Create a temporary SOCKET object called AcceptSocket for accepting connections.

SOCKET AcceptSocket;

 

// Create a continuous loop that checks for connections requests. If a connection

// request occurs, call the accept function to handle the request.

printf("Server: Waiting for a client to connect...\n" );

printf("***Hint: Server is ready...run your client program...***\n");

// Do some verification...

while (1)

{

    AcceptSocket = SOCKET_ERROR;

    while (AcceptSocket == SOCKET_ERROR)

    {

        AcceptSocket = accept(m_socket, NULL, NULL);

    }

 

    // else, accept the connection...

    // When the client connection has been accepted, transfer control from the

    // temporary socket to the original socket and stop checking for new connections.

    printf("Server: Client Connected!\n");

    m_socket = AcceptSocket; 

    break;

}

 

int bytesSent;

int bytesRecv = SOCKET_ERROR;

char sendbuf[200] = "This string is a test data from server";

// initialize to empty data...

char recvbuf[200] = "";

 

// Send some test string to client...

printf("Server: Sending some test data to client...\n");

bytesSent = send(m_socket, sendbuf, strlen(sendbuf), 0);

 

if (bytesSent == SOCKET_ERROR)

       printf("Server: send() error %ld.\n", WSAGetLastError());

else

{

       printf("Server: send() is OK.\n");

       printf("Server: Bytes Sent: %ld.\n", bytesSent);

}

 

// Receives some test string from client...and client

// must send something lol...

bytesRecv = recv(m_socket, recvbuf, 200, 0);

 

if (bytesRecv == SOCKET_ERROR)

       printf("Server: recv() error %ld.\n", WSAGetLastError());

else

{

       printf("Server: recv() is OK.\n");

       printf("Server: Received data is: \"%s\"\n", recvbuf);

       printf("Server: Bytes received: %ld.\n", bytesRecv);

}

 

WSACleanup();

return 0;

}

 

Windows socket program example output screen: using recv() and send() for server

 

Figure 1

 

The following is the client program. As usual, you have to run the server program first.

 

#include <stdio.h>

#include <winsock2.h>

 

int main()

{

  // Initialize Winsock

  WSADATA wsaData;

  int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

  if (iResult != NO_ERROR)

    printf("Client: Error at WSAStartup().\n");

  else

    printf("Client: WSAStartup() is OK.\n");

 

  // Create a SOCKET for connecting to server

  SOCKET ConnectSocket;

  ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (ConnectSocket == INVALID_SOCKET)

  {

    printf("Client: Error at socket(): %ld.\n", WSAGetLastError());

    WSACleanup();

    return 0;

  }

  else

    printf("Client: socket() is OK.\n");

 

  // The sockaddr_in structure specifies the address family,

  // IP address, and port of the server to be connected to.

  sockaddr_in clientService;

  clientService.sin_family = AF_INET;

  clientService.sin_addr.s_addr = inet_addr("127.0.0.1");

  clientService.sin_port = htons(55555);

 

  // Connect to server.

  if (connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR)

  {

    printf("Client: Failed to connect.\n");

    WSACleanup();

    return 0;

  }

  else

    printf("Client: connect() is OK.\n");

 

  // Declare and initialize variables.

  int bytesSent;

  int bytesRecv = SOCKET_ERROR;

  char sendbuf[100] = "Client: Sending some data.";

  char recvbuf[100] = "";

 

  while(bytesRecv == SOCKET_ERROR )

  {

    bytesRecv = recv(ConnectSocket, recvbuf, 100, 0);

    if (bytesRecv == 0 || bytesRecv == WSAECONNRESET)

    {

      printf("Client: Connection Closed.\n");

      break;

    }

    else

    {

       printf("Client: recv() is OK.\n");

       printf("Client: Bytes received: %ld\n", bytesRecv);

    }

  }

 

  // Send and receive data.

  bytesSent = send(ConnectSocket, sendbuf, strlen(sendbuf), 0);

  printf("Client: Bytes sent: %ld\n", bytesSent);

  WSACleanup();

  return 0;

}

 

Windows socket program example output screen: using recv() and send() for client

 

Figure 2

 

And the previous server’s console output.

 

Windows socket program example output screen: using a complete recv() and send() for server

 

Figure 3

 

send()

 

Item

Description

Function

send().

Use

Sends data on a connected socket.

Prototype

int send(SOCKET s, const char* buf, int len, int flags);

Parameters

s

[in] Descriptor identifying a connected socket.

 

buf

[in] Buffer containing the data to be transmitted.

 

len

[in] Length of the data in buf, in bytes.

 

flags

[in] Indicator specifying the way in which the call is made.

Return value

See below.

Include file

<winsock2.h>