I have done alot of stuff with Winsock, but it's all with sockets that can olni process one at a time.
Can anyone tell me how to make a non-blocking socket? [send and recive]
I have done alot of stuff with Winsock, but it's all with sockets that can olni process one at a time.
Can anyone tell me how to make a non-blocking socket? [send and recive]
LMGTFY
Depends on OS, really. For most OS, I believe this is it:
If you happen to be on Windows, it does it differently:Code:int flags = fcntl(socket_fd, F_GETFL); fcntl(socket_fd, F_SETFL, flags (add or remove O_NONBLOCK));
Code:unsigned long what = (0 for blocking, anything else for non-blocking.); ioctlsocket(your_socket, FIONBIO, &what);
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)
Code://try //{ if (a) do { f( b); } while(1); else do { f(!b); } while(1); //}
This is one of mi header files.
Tell me if I did it right.
Code://Socket.cpp #include "Socket.h" Socket::Socket() { if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR ) { cerr<<"Socket Initialization: Error with WSAStartup\n"; system("pause"); WSACleanup(); exit(10); } //Create a socket mySocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); unsigned long what = (4); ioctlsocket(mySocket, FIONBIO, &what); if ( mySocket == INVALID_SOCKET ) { cerr<<"Socket Initialization: Error creating socket"<<endl; system("pause"); WSACleanup(); exit(11); } myBackup = mySocket; } Socket::~Socket() { WSACleanup(); } bool Socket::SendData( char *buffer ) { send( mySocket, buffer, strlen( buffer ), 0 ); return true; } bool Socket::RecvData( char *buffer, int size ) { int i = recv( mySocket, buffer, size, 0 ); buffer[i] = '\0'; return true; } void Socket::CloseConnection() { //cout<<"CLOSE CONNECTION"<<endl; closesocket( mySocket ); mySocket = myBackup; } void Socket::GetAndSendMessage() { char message[STRLEN]; cin.ignore();//without this, it gets the return char from the last cin and ignores the following one! cout<<"Send > "; cin.get( message, STRLEN ); SendData( message ); } void ServerSocket::StartHosting( int port ) { Bind( port ); Listen(); } void ServerSocket::Listen() { //cout<<"LISTEN FOR CLIENT..."<<endl; if ( listen ( mySocket, 1 ) == SOCKET_ERROR ) { cerr<<"ServerSocket: Error listening on socket\n"; system("pause"); WSACleanup(); exit(15); } //cout<<"ACCEPT CONNECTION..."<<endl; acceptSocket = accept( myBackup, NULL, NULL ); while ( acceptSocket == SOCKET_ERROR ) { acceptSocket = accept( myBackup, NULL, NULL ); } mySocket = acceptSocket; } void ServerSocket::Bind( int port ) { myAddress.sin_family = AF_INET; myAddress.sin_addr.s_addr = inet_addr( "0.0.0.0" ); myAddress.sin_port = htons( port ); //cout<<"BIND TO PORT "<<port<<endl; if ( bind ( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress) ) == SOCKET_ERROR ) { cerr<<"ServerSocket: Failed to connect\n"; system("pause"); WSACleanup(); exit(14); } } void ClientSocket::ConnectToServer( const char *ipAddress, int port ) { myAddress.sin_family = AF_INET; myAddress.sin_addr.s_addr = inet_addr( ipAddress ); myAddress.sin_port = htons( port ); //cout<<"CONNECTED"<<endl; if ( connect( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress ) ) == SOCKET_ERROR ) { cerr<<"ClientSocket: Failed to connect\n"; system("pause"); WSACleanup(); exit(13); } }
Generally, you use non-blocking sockets. Using blocking sockets would provide a disadvantage that you would only be able to perform 1 recv() until you would have to return to a select() call. If more data is available then your initial recv() on the socket, then you'll miss out until you call select() again. If you use non-blocking sockets, however, then you can just recv() until there is no more data.
Furthermore, and more seriously, the man page for select() notes that:
As for the OP's code, some notes:Originally Posted by man 2 select
1) You can use INADDR_ANY in place of inet_addr( "0.0.0.0" );
2) If WSAStartup() fails, WSACleanup() is probably unneeded.
3)do-while?Code:acceptSocket = accept( myBackup, NULL, NULL ); while ( acceptSocket == SOCKET_ERROR ) { acceptSocket = accept( myBackup, NULL, NULL ); } mySocket = acceptSocket;
4) '4' is an arbitrary number... just because the man page said 'non-zero' doesn't mean you have to follow it that closely. Try something more sane, like... 1? Otherwise, readers are going to be wondering what '4' does.
5) In SendData(), check the return value. send() might not send() everything you ask of it, especially with non-blocking sockets.
5) RecvData has a buffer overflow.
First, check that return value. If something goes wrong (ie, error, or since it's a non-blocking socket, it signals that it would block) then it will return negative, and you'll have buffer[negative #], which is obviously not a Good Thing™. Furthermore, in the case of extreme success, recv() actually recv's size bytes, it'll return size, and buffer[size] is off by one. (If it's string data though, you do need to terminate that buffer though! recv() size-1, and make sure that recv()'s ret isn't negative!)Code:bool Socket::RecvData( char *buffer, int size ) { int i = recv( mySocket, buffer, size, 0 ); buffer[i] = '\0'; return true; }
Last edited by Cactus_Hugger; 07-03-2009 at 12:56 PM.
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)