Click here to Skip to main content
15,885,278 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Currently I am working on a single server,single client udp chat application. Initially I used blocking sockets which is the default condition. Now I want to convert the socket into non-blocking so that communication between client and server could be done without the obstacle of turns... I've implemented the select function on the server side for now,but the when it starts the client gets to send a message once which is displayed on the server side,afterwards both client and server get irresponsive, so now I am showing how have I implemented the select() function on the server side:
//Declaring a non-blocking structure
              fd_set readfds,writefds;
           // clear the set ahead of time
              FD_ZERO(&readfds);
              FD_ZERO(&writefds);
           // add our descriptor to the set
              FD_SET(sd, &readfds);
              FD_SET(sd, &writefds);
              /value of sd+1
              int n=sd+1;


Since I want to both receive and send data,I've implemented the select funtion in the loop:

int client_length = (int)sizeof(struct sockaddr_in);
                int rv = select(n, &readfds, NULL, NULL, NULL);
                if(rv==-1)
                {
                 printf("Error in Select!!!\n");
                 exit(0);
                }
               else if(rv==0)
                { 
                 printf("Timeout occurred\n");
                }
               else 
                if (FD_ISSET(sd, &readfds))
                {
                int bytes_received = recvfrom(sd, buffer,SIZE, 0, (struct sockaddr *)&client, &client_length);
                if (bytes_received < 0)
               {
               fprintf(stderr, "Could not receive datagram.\n");
               closesocket(sd);
               WSACleanup();
               exit(0);
              }
                }


further for sending data:

fgets(buffer,SIZE,stdin);
              int rv1 = select(n, &writefds, NULL, NULL, NULL);
              if(rv1==-1)
              {
           printf("Error in Select!!!\n");
           exit(0);
              }
             else if(rv1==0)
             {
            printf("Timeout occurred\n");
             }
            else 
             if(FD_ISSET(sd,&writefds))
                  {
                     if(sendto(sd, buffer,strlen(buffer), 0, (struct sockaddr *) &client,client_length)<0)
                         {
                            printf("Error sending the file! \n");
                            exit(1);
                         }
                  }

                }
Posted
Comments
Sergey Alexandrovich Kryukov 15-Apr-13 2:16am    
Why? I hoped non-blocking sockets will go as threading becomes a commonplace. Better use threads with blocking calls. It makes code more linear, straightforward, more universal.
—SA
parths 15-Apr-13 2:53am    
If we used threading, wouldn't it depend on how many concurrent connections we want to support? For instance, if we have more than about 10-15K connections the context switching between the threads could become a bottleneck, right? Also anything about 32K connections (meaning 32K threads) would probably be unfeasible.
Sergey Alexandrovich Kryukov 15-Apr-13 3:05am    
No. The same thread is used for many connections. One example: TCP socket on client side. Two threads are minimally required: one accepts new connections, another one sends/receives data to/from remote sockets. Similar approached for different scenarios.

There are many people arguing against threads, but all arguments are reduced to one: they show the case if idiotic misuse of threads and then say: "look how bad!".

—SA
parths 15-Apr-13 3:13am    
But if we use the same thread for multiple connections, wouldn't each connection in any one thread have to be asynchronous / non-blocking? Otherwise the thread would block on the first blocking call and wouldn't be able to process any other connections that it has. Am I missing something?
Sergey Alexandrovich Kryukov 15-Apr-13 3:30am    
Look at this in this way: all your async APIs are implemented as threads anyway, but hidden from your...
No, there is no the limitation you mentioned. Why having async at all?
—SA

I couldn't see any calls setting the socket to work in non-blocking mode. Did you take a look at ioctl[^] (optionally ioctlsocket[^] for win32) with the FIOASYNC and/or FIOBNIO[^] options?

Here's the first tut link[^] I got from google. You might find better ones.

I hope this helps

[Modification] Also, depending on you requirement and other load expectations, as Sergey pointed out above, using threads with blocking calls should be considered [/Modification]
 
Share this answer
 
v2
You have to turn the socket into nonblocking mode even if you are using select() and its friends. On some versions of windows select() is able to wake up spuriously because the network stack receives some data but when you actually start reading the socket it can find out that the crc of the received data isn't OK leaving your reading in a blocking state if the socket isn't turned into non-blocking. This may happen also on non-windows OS-es. Another problem with your code is that you should handle the wait for read/write operations with a single select call.
C++
int rv = select(n, &readfds, &writefds, NULL, NULL);
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900