E1696 E0020 errors using VS

Pages: 123
Do you actually have start from scratch?
The dlib library comes with a simple server class, might be easier to build on top of it.
http://dlib.net/network.html

Another option is to use boost.
https://theboostcpplibraries.com/boost.asio-network-programming
Last edited on
I need ... How can this be done using asynchronous stream sockets with winsock?
You don't need to start with asynchronous i/o; however, boost does have several examples of asio sockets, and do provide an echo client/server example.

boost asio is a little complicated/arbitrary, and you have to take a lot of it in good faith until you're comfortable with it. However, under the covers, it's making the right calls to the platform's async i/o mechanisms. However, it's only worth the pain if you need the performance.

Poco is little more conventional and thus easier to understand, and is used in performant network libraries (like FIX8). If you just want to get your project going, I'd recommend starting with that. https://pocoproject.org/slides/200-Network.pdf
Last edited on
I need to start from the scratch using sockets. I am not familiar with boost nor any other 3rd party libraries. Is there any other alternate options?
the unix sockets are likely ported and usable on windows. The unix ones are like the original winsock, almost identical but for a name or two or parameter or two here and there. The second generation windows sockets (and beyond? have they redone it again?) was easier to use and much simpler. Do you need it to run on unix too?
Last edited on
Ideally must be for winsock, but good to have it support for unix as well.
do you mean there is already some porting done already?
Below is the sample snippet code for client in unix. how can i port it for winsock?

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

#include  <stdlib.h>
#include  <stdio.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <netinet/in.h>
#include  <string.h>
#include  <arpa/inet.h>

#define  MAXLINE  4096  /*max  text  line  length*/
#define  SERV_PORT  2000  /*port*/

int
main(int  argc,  char  **argv)
{
 int  sockfd;
 struct  sockaddr_in  servaddr;
 char  sendline[MAXLINE],  recvline[MAXLINE];

 //basic  check  of  the  arguments
 //additional  checks  can  be  inserted
 if  (argc  !=2)  {
   printf("Usage:  Client  <IP  address  of  the  server");
   exit(1);
 }

 //Create  a  socket  for  the  client
 //If  sockfd<0  there  was  an  error  in  the  creation  of  the  socket
 if  ((sockfd  =  socket  (AF_INET,  SOCK_STREAM,  0))  <0)  {
   printf("Problem  in  creating  the  socket");
   exit(2);
 }

 //Creation  of  the  socket
 memset(&servaddr,  0,  sizeof(servaddr));
 servaddr.sin_family  =  AF_INET;
 servaddr.sin_addr.s_addr=  inet_addr(argv[1]);
 servaddr.sin_port  =    htons(SERV_PORT);  //convert  to  big-endian  order

 //Connection  of  the  client  to  the  socket
 if  (connect(sockfd,  (struct  sockaddr  *)  &servaddr,  sizeof(servaddr))<0)  {
   printf("Problem  in  connecting  to  the  server");
   exit(3);
 }

 while  (fgets(sendline,  MAXLINE,  stdin)  !=  NULL)  {

   send(sockfd,  sendline,  strlen(sendline),  0);

   if  (recv(sockfd,  recvline,  MAXLINE,0)  ==  0){
     //error:  server  terminated  prematurely
     printf("The  server  terminated  prematurely");
     exit(4);
   }
   printf("%s",  "String  received  from  the  server:  ");
   fputs(recvline,  stdout);
 }

 exit(0);
}




Below is the server unix code.


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
#include  <stdlib.h>
#include  <stdio.h>
#include  <sys/types.h>
#include  <sys/socket.h>
#include  <netinet/in.h>
#include  <string.h>
#include  <unistd.h>

#define  MAXLINE  4096  /*max  text  line  length*/
#define  SERV_PORT  2000  /*port*/
#define  LISTENQ  100  /*maximum  number  of  client  connections*/

int  main  (int  argc,  char  **argv)
{
 int  listenfd,  connfd,  n;
 pid_t  childpid;
 socklen_t  clilen;
 char  buf[MAXLINE];
 struct  sockaddr_in  cliaddr,  servaddr;

 //Create  a  socket  for  the  soclet
 //If  sockfd<0  there  was  an  error  in  the  creation  of  the  socket
 if  ((listenfd  =  socket  (AF_INET,  SOCK_STREAM,  0))  <0)  {
   printf("Problem  in  creating  the  socket");
   exit(2);
 }


 //preparation  of  the  socket  address
 servaddr.sin_family  =  AF_INET;
 servaddr.sin_addr.s_addr  =  htonl(INADDR_ANY);
 servaddr.sin_port  =  htons(SERV_PORT);

 //bind  the  socket
 bind  (listenfd,  (struct  sockaddr  *)  &servaddr,  sizeof(servaddr));

 //listen  to  the  socket  by  creating  a  connection  queue,  then  wait  for  clients
 listen  (listenfd,  LISTENQ);

 printf("%s\n","Server  running...waiting  for  connections.");

 for  (  ;  ;  )  {

   clilen  =  sizeof(cliaddr);
   //accept  a  connection
   connfd  =  accept  (listenfd,  (struct  sockaddr  *)  &cliaddr,  &clilen);

   printf("%s\n","Received  request...");

   if  (  (childpid  =  fork  ())  ==  0  )  {//if  it’s  0,  it’s  child  process

   printf  ("%s\n","Child  created  for  dealing  with  client  requests");

   //close  listening  socket
   close  (listenfd);

   while  (  (n  =  recv(connfd,  buf,  MAXLINE,0))  >  0)    {
     printf("%s","String  received  from  and  resent  to  the  client:");
     puts(buf);
     send(connfd,  buf,  n,  0);
   }

   if  (n  <  0)
     printf("%s\n",  "Read  error");
   exit(0);
 }
 //close  socket  of  the  server
 close(connfd);
}
}

not sure if you can find a full port. but you can wrap an interface around both and #define which is active with very little work, they are extremely similar if you dig down into the lower level winsock functions. Searching indicates others have done this and put it out on git. Or you can use cygwin to pull the unix ones to windows, though making cygwin library talk to visual is tricksy at times.
I mean, look at what you posted :) Its not even 50 lines of code... this should be no more than a day's work to figure out.
@leo2008, can you confirm you understand the code. If you don't please ask about what you don't. I don't want to provide you with code you don't understand.

Your code is a mess. If you can't read it, you can't work with it. I've changed it, mostly to make it readable. I'll do the Windows port after. How much I explain depends on how much you want to know about how a basic TCP server works.

I've used SOCKET instead of int on Unix to pave the way to the Windows port.

Windows doesn't have fork(), so you're pretty much forced to run the client handler in a separate thread, so I've moved the handler out to a function.

Finally, it compiles as a C or C++ program.
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
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifndef _WIN32
#define SOCKET int
#endif

#define MAXLINE     4096  /*max  text  line  length*/
#define SERV_PORT   2000  /*port*/
#define LISTENQ     100  /*maximum  number  of  client  connections*/

void handle_client(SOCKET client_sock);

int main(int argc, char** argv) {
    int rc;

    // create server socket
    SOCKET server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if  (server_sock == -1) {
        printf("%s\n", "socket() failed");
        exit(2);
    }

    // socket address
    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    // bind socket to the address
    rc = bind(server_sock, (struct sockaddr*)&servaddr, sizeof(servaddr));
    if (rc == -1) {
        printf("%s\n", "bind() failed");
        exit(2);
    }

    // listen to the socket by creating a connection queue, then wait for clients
    rc = listen(server_sock, LISTENQ);
    if (rc == -1) {
        printf("%s\n", "listen() failed");
        exit(2);
    }

    printf("%s\n", "Server running...waiting for connections");
    for (;;) {
        struct sockaddr_in clientaddr;
        socklen_t clientlen = sizeof(clientaddr);
        SOCKET client_sock = accept(server_sock, (struct sockaddr*)&clientaddr, &clientlen);
        printf("%s\n", "Received client connection");

        pid_t childpid = fork();
        if (childpid == 0) {
            close(server_sock); // child shouldn't see server socket
            handle_client(client_sock);
            close(client_sock); // we're done
            exit(0);
        }

        close(client_sock); // server shouldn't see client socket
    }
}

void handle_client(SOCKET client_sock) {
    printf("%s\n","Child process created for handling client");

    ssize_t nbytes;
    char buf[MAXLINE];
    while ((nbytes = recv(client_sock, buf, MAXLINE, 0)) > 0) {
        buf[nbytes] = 0; // null terminate the request
        printf("%s\n\t%s\n","String received from and resent to the client:", buf);
        send(client_sock, buf, nbytes, 0);
    }
    printf("%s\n", "Read complete");

    close(client_sock);
}
Last edited on
Hi kbw

Thanks for the code modifications.
I understand that winSock does not use int to represent sockets, it uses SOCKET instead, which is a UINT_PTR. When checking for an invalid socket handle, don't use < 0, use == INVALID_SOCKET instead.

Most socket functions return error codes via WSAGetLastError() (WSAStartup() being an exception to that).

I see that you are creating child process for every client socket connections. The client which got connected already with server disconnects later on, any way to reconnect it back to the same server? Also when there is more than 1 server, is it possible to send a consolidate info about all the available servers info to client, so that client can connect to one of them?
Last edited on
Below is what i have tried so far. Please feel free to modify it, as I need to use c++.

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
97
98
99
100
101

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

#define BUFFER_SIZE 1024

#pragma comment(lib, "ws2_32.lib")

void with_error(char *s, int *errCode = NULL)
{
    int err = (errCode) ? *errCode : WSAGetLastError();
    fprintf(stderr, "%s: %d\n", s, err);
    fflush(stderr);
    exit(1);
}

int main(int argc, char *argv[])
{
    WSADATA wsadata; 
    SOCKET server_fd, client_fd;
    struct sockaddr_in server, client;
    int port = 5555, err; 
    char buf[BUFFER_SIZE];

    err = WSAStartup(MAKEWORD(2,2), &wsadata);
    if (err != 0)
        with_error("Error in WSAStartup", &err);

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == INVALID_SOCKET)
        with_error("Error creating socket");

    memset(&server, 0, sizeof(server)); 
    server.sin_family = AF_INET; 
    server.sin_port = htons(port); 
    server.sin_addr.s_addr = INADDR_ANY; 

    /** bind & listen **/
    const BOOL optval = TRUE;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval));
    err = bind(server_fd, (struct sockaddr *) &server, sizeof(server));
    if (err == SOCKET_ERROR)
        with_error("Not able to bind the socket");
    err = listen(server_fd, 1);
    if (err == SOCKET_ERROR)
        with_error("Not able to listen on the socket");

    printf("SERVER LISTENING ON PORT %d\n", port);

    while (1)
    {
        int clientlen = sizeof(client);
        client_fd = accept(server_fd, (struct sockaddr *) &client, &clientlen);

        if (client_fd == INVALID_SOCKET)
            with_error("Not able to setup a new connection");

        bool keepLoop= true;
        do
        {
            int read = recv(client_fd, buf, BUFFER_SIZE, 0);

            if (read == 0)
                break;

            if (read == SOCKET_ERROR)
            {
                err = WSAGetLastError();
                if ((err != WSAENOTCONN) && (err != WSAECONNABORTED) && (err == WSAECONNRESET))
                    with_error("Error reading from client", &err);
                break;
            }

            char *pbuf = buf;
            do
            {
                int sent = send(client_fd, pbuf, read, 0);
                if (sent == SOCKET_ERROR)
                {
                    err = WSAGetLastError();
                    if ((err != WSAENOTCONN) && (err != WSAECONNABORTED) && (err == WSAECONNRESET))
                        with_error("Error writing to client", &err);

                    keepLoop = false;
                    break;
                }

                pbuf += sent;
                read -= sent;
            }
            while (read > 0);
        }
        while (keepLoop);

        closesocket(client_fd);
    }

    WSACleanup();
    return 0;
}
Last edited on
Ok, that looks good. However, you've gone backwards from what I posted.

Importantly:
* You're removed the client handler from being in a function, to be inline. So it can't be run in a thread easily, your server can only handle one client at a time. So it makes sense for listen() to be passed 1, but why the constraint?

Less importantly:
* You've changed the call to socket(), dunno why

Does it work for you?
Do you understand why there's a loop around send()?
I expect you'll need to handle clients concurrently. We can fix that.
I have not tested it. Moreover this is just a sample and loop around send is to keep monitoring for any read errors from client. I will need to modify to handle multiple clients. but what happens if multiple clients send message at same time to server? how do we handle such case? Use std::thread class in c++?
that should be handled for you. the socket library should be doing this behind the scenes... what happens (oversimplified) is some sort of queue of messages is loaded and they are 'sorted' by IP address or something of the sender to keep it all organized. As long as you are reading the data out reasonably quickly it will just work. If you stop reading, eventually something will go wrong if the sender keeps piling up more data. There should be errors thrown or at least flags set that you can query to know that things went wrong, but you can table that until you get the basics down.

if you have multiple connections, your code needs to track who gets what, though. The incoming packets have the sender's ID on them, and you need to retain that and reply to the correct sender with the correct responses. Threading helps simplify this side of it -- you organize the data and farm it out to the correct thread, so each one is really only handling 1 connection. Get the 1 connection working, then, and if you plan to have more, split it into functions that you foresee being threads later, and it will just work when you extend the # of connections.

If this is a HUGE server, handing more than 10s of connections at a time, you need to plan and design better though. Just slapping it together is fine for a few connections, but once the machine starts to get busy, you need to start looking at performance etc.
I have not tested it.
You should. It's easy because the client can be netcat or telnet ... a number of things.

I will need to modify to handle multiple clients.
I don't get the impression that you're trying to learn anything here, just to get some working code that you can use.

If you're not interested in understanding it, why not use a library as I suggested right at the start?
My sample code doesnt work, im trying to fix it. The client which gets connected already with server disconnects later on due to some reason like timeout or something else. Is there any way to reconnect it back to the same server?
Last edited on
What objection do have to using, say Poco, rather than writing this stuff from scratch?
I have come up with the below function, in case client which was connected to server already and later on disconnects due to some reason like timeout or so. In that case to handle reconnecting to the same server, can this be done or should I close and reconnect to the server again??

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
retryconnect(int sockfd, const struct sockaddr *addr, socklen_t alen)
{
    int nsec;

    /*
     * Try to connect with exponential backoff.
     */

    for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
        if (connect(sockfd, addr, alen) == 0) {

            /*
             * Connection accepted.
             */

            return(0);
        }

        /*
         * Delay before trying again.
         */

        if (nsec <= MAXSLEEP/2)
            sleep(nsec);
    }
    return(-1);
}
Last edited on
If you're disconnected and need to reconnect, you should close the old socket handle before starting a new connection.

That will clear down the old connection, as TCP is designed to try to maintain a connection.

When you close it, you'll need to call socket()/connect() again.
Ok, so whenever client loses connection with server, it has to close and start new connection always?
Last edited on
Ok, so whenever client loses connection with server, it has to close and start new connection always?
-- yes, as far as I know, once it is closed it is dead and you have to start over. Its a lot like a file stream.. once you close it, the only way back is to open it again.

multiple instances of what, the program? threads? This is unclear, what are you calling 'the server' here?

your one and only program can manage a container of connections to other machines. you just iterate the container and handle each one in turn, whether that is threaded or just a dumb loop.

again, think of it a little like files. how do you open 3 files at once? You need 3 file stream variables, each open to a different file...

there are ways to broadcast the same info so that anyone listening picks it up. Is that the model you want? That works kind of like a radio ... everyone can listen to the same station at once, but if you turn it off, you lose out and can't get it back. It would help if you explained what you want to do very precisely. No offense but your posts when put together read like your software is both the client and the server, and it is connecting to stuff and being connected to, and it is broadcasting but not broadcasting...


Pages: 123