WinSock program error

Pages: 12
Hi All,

When I run a simple winsock program it returns the following error.

recv failed: 10054

Can some one help me to rectify this error? I also activated another udp sender application to inject udp packets into 127.0.0.1 10. Then I wanted to read the packets at port 10 from the code shown below. Is it something workable. Sorry for my little knowledge about how Winsock work.

Winsock program is as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "10"

int main(){

    //----------------------
    // Declare and initialize variables.
    WSADATA wsaData;
    int iResult;

    SOCKET ConnectSocket = INVALID_SOCKET;
    struct sockaddr_in clientService; 

    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;
  
    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR) {
          printf("WSAStartup failed: %d\n", iResult);
          return 1;
    }

    //----------------------
    // Create a SOCKET for connecting to server
    ConnectSocket = socket(AF_INET, SOCK_DGRAM, 0);
    if (ConnectSocket == INVALID_SOCKET) {
           printf("Error at socket(): %ld\n", WSAGetLastError() );
           WSACleanup();
           return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    clientService.sin_port = 10;

    //----------------------
    // Connect to server.
    iResult = connect( ConnectSocket, (SOCKADDR*) &clientService,      sizeof(clientService) );
    if ( iResult == SOCKET_ERROR) {
           closesocket (ConnectSocket);
           printf("Unable to connect to server: %ld\n", WSAGetLastError());
           WSACleanup();
           return 1;
    }

    // Send an initial buffer
   iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
           printf("send failed: %d\n", WSAGetLastError());
           closesocket(ConnectSocket);
           WSACleanup();
           return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // Receive until the peer closes the connection
    while((iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0)) != 0) 
         // continue till disconnected
  {
         if(iResult == -1)
        {
              if(WSAGetLastError() == WSAEMSGSIZE) // server has more data to send than the buffer can get in one call
             {
                   continue; // iterate again to get more data
             } else {
             // some other error
                   printf("recv failed: %d\n", WSAGetLastError());
             }
     } else {
      // if iResult is numeric then it has retrieved what it needed and no more is currently available so if we call recv() again it will block.
            printf("Bytes received: %d\n", iResult);
            break;
     }
  }
  if(!iResult)  printf("Connection closed\n");

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}


Best Regards
erhct
Last edited on
Hey, can u edit ur code with code that has proper indentation like this:
1
2
3
4
5
while(hoursBeforeWork != 0)
{
    DrinkBeer(1);
    --hoursBeforeWork;
}


I might be able to help because I'm learning the same stuff except with TCP but I can't read what u wrote...
Last edited on
The server has closed the connection. You need to take a look at the server, the client code looks fine.
Thanks kbw for the reply!

May be my understanding is wrong. I dont have a server side. I want to basically listen to port 10 and get the datagrams into a buffer. I have a separate program to inject udp packets to 127.0.0.1 port 10. Is this possible with this code or do I have to try something else.

Hi Soranz,

I re-posted the code with proper indentation (pls see the beginning of this discussion). Please help.

Looking forward to your help.

Regards
erhct
May be my understanding is wrong. I dont have a server side. I want to basically listen to port 10 and get the datagrams into a buffer. I have a separate program to inject udp packets to 127.0.0.1 port 10.
You have a TCP client. If you want to receive UDP traffic, you'll need to write a client that uses UDP, not TCP.

It is possible to have multiple UDP clients write to any given server:port combination, and the listener can receive those packet. You have to:
1. create a UDP socket
2. bind to the interface:port (probably INADDR_ANY:10 in your case)
3. use recvfrom to listen to receive packets. The function will tell you what socket address it received the packet from.

UDP is much easier to use than TCP, but you should be aware that UDP is "unreliable". It'll work perfectly on a subnet, but you'll need error correction if you're running on a potentially busy LAN or a WAN.
Last edited on
Thanks kbw!
It worked after the modification you proposed. But the program exits after it received the first datagram. How I can make sure it does not exit till I receive all the packets from that port. The code is shown below,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int main()
{

    int iResult = 0;
	FILE* fOutPut;
    WSADATA wsaData;

    SOCKET RecvSocket;
    sockaddr_in RecvAddr;

    unsigned short Port = 10;//27015

	int BufLen = 1024;
    char RecvBuf[1024];
    

    sockaddr_in SenderAddr;
    int SenderAddrSize = sizeof (SenderAddr);

    //-----------------------------------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error %d\n", iResult);
        return 1;
    }
    //-----------------------------------------------
    // Create a receiver socket to receive datagrams
    RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (RecvSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error %d\n", WSAGetLastError());
        return 1;
    }
    //-----------------------------------------------
    // Bind the socket to any address and the specified port.
    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_port = htons(Port);
	//RecvAddr.sin_port = 10;
    RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
    if (iResult != 0) {
        wprintf(L"bind failed with error %d\n", WSAGetLastError());
        return 1;
    }
    //-----------------------------------------------
    // Call the recvfrom function to receive datagrams
    // on the bound socket.
    wprintf(L"Receiving datagrams...\n");
    iResult = recvfrom(RecvSocket,
                       RecvBuf, BufLen, 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
    }

	fOutPut=fopen("out.txt", "wb");
	fwrite(&RecvBuf, sizeof(char), 1000,fOutPut);
	fclose(fOutPut);
 
    //-----------------------------------------------
    // Close the socket when finished receiving datagrams
    wprintf(L"Finished receiving. Closing socket.\n");
    iResult = closesocket(RecvSocket);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
        return 1;
    }

    //-----------------------------------------------
    // Clean up and exit.
    wprintf(L"Exiting.\n");
    WSACleanup();
    return 0;
}


Looking forward to your comments...

Regards
erhct
Should there be a loop around iResult = recvfrom(RecvSocket, ... ?
Thanks Soranz! I managed to collect all datagram packets send by the sender programme through a loop. But still the programe listen to incoming packets.

How I can stop listening when there are no more packets for instance after 5s.

Regards
erhct
How I can stop listening when there are no more packets for instance after 5s.
You can use select() to wait for incoming packets with a timeout.

If the socket is available for read, you read it. If select() timed out, you drop out of the loop.
Thanks Kbw!!!

Still I couldn't figure out how select() works with a listening socket. Can someone provide a sample code how select() works with udp listening socket.

Regards
erhct
http://www.codeproject.com/Articles/20066/A-scalable-client-server-using-select-socket-funct

There's a definition of select() and if you go down to the AcceptConnections() function u'll see it in action for the listening socket.
select() allows you wait for sets of sockets to signal for read, write or error. An you can set a timeout.

There are macros that manage the sets and allow to test if one is set. If your case you'll only be testing one socket for read, with a 5 sec timeout.

1. You define an fd_set and initialise it with FD_ZERO.
2. You use FD_SET to add your socket to the set.
3. Initialise a struct timeval record with { 5, 0 } for 5 sec, 0 nsec
4. Call select() with the read set specified and zero for the write and error. It returns the number of sockets signalled, zero for timeout.
5. If select() returned 1, you can read the socket. As you only have the one socket, you can be sure that FD_ISSET will confirm that your socket is readable.
Thanks Soranz and Kbw! I managed to implement the timeout using the select() function after specifying necessary parameters.

Can you pls shed some light on whether I can find the index no of received udp packets. In this case I can find the missing packets from the total transmitted packets.

Looking forward to hear from you

Best Regards
erhct
There is no index number of a udp packet. You have to maintain that yourself.
Thanks!

I created a separate thread to read udp packets. But when I tried to call a function declared with the main programme (main()) it does not identify the function.

Error: undeclared identifier

My function declared as follows:

DWORD CALLBACK xxx()

I called this function within the thread from another function using the following syntax

function(&xxx,etc);

thread is created as follows.
1
2
3
4
5
6
_beginthreadex( NULL,
                                          0,
                                          read_udp_data,
                                          NULL,
                                          0, 
                                          &uiThreadID0 );


This function works well within the main() but not within the thread()
I think I am not calling the function correctly.
Can someone help pls.

Regards
erhct
I don't understand the problem from your description. Can you post some code that demonstrates what the problem is and what you've done.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int __stdcall streamcreate(WRITEPROC *MyStreamWriter);


DWORD CALLBACK MyStreamWriter(HSTREAM handle, void *buf, DWORD len, void *user)
{

//

}

unsigned int __stdcall read_udp_data(void* data)
{

streamcreate(&MyStreamWriter);

}

int main( int argc, char *argv[] )
{

_beginthreadex( NULL,
                                          0,
                                          read_udp_data,
                                          NULL,
                                          0, 
                                          &uiThreadID0 );
return 0;
}


When I call streamcreate function from the thread (read_udp_data) it returns an error during building (undeclared identifier)
Is all the code in the same file as you imply above?

What is the exact error produced by the compiler?
Hi kbw,

Indeed the streamcreate() is from a separate dll. But it is linked to the main progrm.

The error error C2065: 'MyStreamWriter' : undeclared identifier

When I call this function within the main() (e.g. streamcreate(&MyStreamWriter);)it works fine But not from the thread...

Probably I am not passing an instance of MystreamWriter correctly to the streamcreate()
Pages: 12