PDA

View Full Version : Setting up a Non-Blocking Socket (Windows)


tal0n
05-26-2003, 11:45 PM
Yes I know the name of the BBS so please don't mention it :). I need to set a Windows socket to Non-Blocking and my attempts at searching have obviously failed. Sooner the better I hate to mention it but this project is due tomorrow and i believe the only true error in it is that it is blocking.

tal0n
05-27-2003, 01:35 AM
Or atleast help me with this. Problems arise at run time in both the server and client. First off in the Client the names are sent fine and recieved but the prompt for the user to begin typing does not appear until the server sends something to it. Then after something is sent to it (it displays it fine) the clients stops. It does not display the prompt again and will not accept input which leads me to believe that it is blocking somewhere and I thought that I fixed that with the ioctlsocket(). In the server you can send information to the client but after that first send it stops in the same fashion as the client. Here is the full source:

#include <winsock.h>
#include <string.h>
#include <iostream.h>
#include "tal0n.h"
#define PORT 5050
#define MAX 256

int main()
{
WSADATA info;
int status = 0;
u_long NonBlock = 1;
int Wait = -1;
int nbytes = 1;
tal0n chat;

if ( WSAStartup(MAKEWORD(1, 1), &info) != 0 )
{
cerr << "Error in WSAStartup." << endl;
return 0;
}

while ( status != 3 )
{
int choice = chat.Display();
switch ( choice )
{
case 1: // Server
{
fd_set readfds, master;
int control = 0, len;
int sockfd, newfd = -1, curfd, fdmax;
char ReC[MAX], MsG[MAX], Name[20], Them[MAX];
struct sockaddr_in client;

FD_ZERO( &master );
FD_ZERO( &readfds );

sockfd = chat.ServerSet( PORT );
FD_SET( sockfd, &master );
fdmax = sockfd;

cout << "Running..." << endl;
if ( ioctlsocket( sockfd, FIONBIO, &NonBlock ) == SOCKET_ERROR )
{
cout << WSAGetLastError() << endl;
return 0;
}

while ( 1 )
{
readfds = master;
if ( select( fdmax+1, &readfds, NULL, NULL, NULL ) <= 0 )
{
cerr << "Error in Call to Select()" << endl;
closesocket( sockfd );
return 0;
}
for ( int i=0; i <= fdmax; i++ )
{
if ( FD_ISSET( i, &master ) )
{
if ( i == sockfd )
{
if ( control == 0 )
{
cout << "newuser" << endl;
int sin_size = sizeof(struct sockaddr);
if ( (newfd = accept( sockfd, (struct sockaddr *)&client, &sin_size)) == -1 )
{
cout << "Error in accept" << endl;
return 0;
}
else
{
if ( ioctlsocket( newfd, FIONBIO, &NonBlock ) == SOCKET_ERROR )
{
cout << WSAGetLastError() << endl;
return 0;
}
cout << "Waiting for Screen Name." << endl;
while( Wait == -1 )
{
if ( (Wait = recv(newfd, Them, MAX, 0)) > 0 )
break;
}
Wait = -1;
cout << "You are talking with " << Them << endl;

cout << "Enter you screen name for today's conversation: ";
cin >> Name;
cout << "Sending your name." << endl;
if ( send( newfd, Name, strlen(Name), 0 ) == -1 )
{
cerr << "Error in Send" << endl;
return 0;
}
cout << "Name sent." << endl;
}
curfd = newfd;
}
control++;
}
else if( i == newfd )
{
cout << "person talking2" << endl;
if ( (nbytes = recv( i, ReC, MAX, 0 )) <= 0 )
{
cerr << "The Client has disconnected." << endl;
return 0;
}
else if ( nbytes > 0 )
{
strcat( Them, ": " );
strcat( Them, ReC );
for ( int i = 0; (unsigned)i < strlen(Them); i++ )
cout << Them[i];
cout << endl;
}
}
}
}


cout << "] ";
cin.ignore( 80, '\n' );
cin.getline( MsG, MAX, '\n' );
len = strlen( MsG );
if ( len > MAX )
cout << "Your entered message is too long." <<endl;
else
{
if ( chat.quitme( MsG ) == 1 )
{
if ( send( curfd, MsG, len, 0 ) == -1 )
{
cerr << "Error in SenD (Bad)." << endl;
closesocket(newfd);
return 0;
}
cout << "You have quit" << endl;
}
else
{
if ( send( curfd, MsG, len, 0) == -1 )
{
cerr << "Error in SenD (Good)." << endl;
closesocket(newfd);
return 0;
}
cout << "Good" << endl;
}
}
}
break;
}



case 2: // Client
{
fd_set readfds, master;
char RemoteIP[20];
int sockfd, fdmax;
char RecV[MAX], MyName[20], HisName[MAX], BuF[MAX];

FD_ZERO( &master );
FD_ZERO( &readfds );
cout << "Enter the IP to connect to: ";
cin >> RemoteIP;
sockfd = chat.ClientSet( RemoteIP, PORT );
if ( ioctlsocket( sockfd, FIONBIO, &NonBlock ) == SOCKET_ERROR )
{
cout << WSAGetLastError() << endl;
return 0;
}
FD_SET( sockfd, &master );
fdmax = sockfd;
cout << "Enter your desired screen name: ";
cin >> MyName;
cout << "Sending Screen Name." << endl;
if( send( sockfd, MyName, strlen(MyName), 0) == 0 )
{
cerr << "Error in Send." << endl;
closesocket(sockfd);
return 0;
}
cout << "Screen Name sent." << endl;

cout << "Retrieving Screen Name." << endl;
while( Wait == -1 )
{
if ( (Wait = recv(sockfd, HisName, MAX, 0)) > 0 )
break;
}
Wait = -1;
cout << "You are now talking with " << HisName << endl;

while( 1 )
{
readfds = master;
if ( select( fdmax+1, &readfds, NULL, NULL, NULL ) <= 0 )
{
cerr << "Error in Call to Select()" << endl;
closesocket( sockfd );
return 0;
}

if ( FD_ISSET( sockfd, &readfds ) )
{
if ( (nbytes = recv( sockfd, RecV, MAX, 0)) <= 0 )
{
cerr << "The server has disconnected." << endl;
closesocket( sockfd );
return 0;
}
else if ( nbytes > 0 )
{
strcat( HisName, ": " );
strcat( HisName, RecV );
for( int i = 0; (unsigned)i < strlen(HisName); i++ )
cout << HisName[i];
cout << endl;
}
}

int MsgLen;
cout << "] ";
cin.ignore( 80, '\n' );
cin.getline( BuF, MAX, '\n' );
MsgLen = strlen( BuF );

if ( MsgLen > MAX )
cout << "You entered to big of a message." << endl;
else
{
if ( chat.quitme( BuF ) == 1 )
{
if ( send( sockfd, BuF, MsgLen, 0 ) == -1 )
{
cerr << "Error in SenD." << endl;
closesocket(sockfd);
return 0;
}
cout << "You have quited" << endl;
}
else
{
if ( send( sockfd, BuF, MsgLen, 0) == -1 )
{
cerr << "Error in SenD." << endl;
closesocket(sockfd);
return 0;
}
cout << "Good" << endl;
}
}
}
break;
}

case 3:
{
cout << "Goodbye" << endl;
break;
}

default:
cerr << "Invalid choice. Please try again." << endl;
break;
}
status = choice;
}
}


This is different than the one that I have been working on in the fact that is is peer-to-peer instead of many clients. Help is GREATLY appreciated at this point.