PDA

View Full Version : Chat not Sending


tal0n
05-21-2003, 10:17 PM
You know me and I know you. You know about this project and I hope you can help. Problem this time is that the client is not recieving the text that another one is sending. I at this point do not care if i get junk or what not. The client will type something and then the prompt for the next line comes up. If someone tries to send text to it then nothing shows up on the screen.


//Client tal0n
#include "tal0n_.h"
#include "list.h"
#include <iostream.h>
#include <stdlib.h>
#define PORT 9090
#define LENGTH 1500

struct sockaddr_in them;
fd_set readfds, writefds, master;

int main(int argc, char *argv[])
{
tal0n_ cl;
char yn;
char buf[LENGTH], rec[LENGTH];
char name[20];
int top;
int fdmax, len;
int ip1,ip2,ip3,ip4;
WSADATA info;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&master);

// Initialize them arrays so I get good values later
cl.init( buf );
cl.init( rec );

// Fix this process up later. Make it friendly for the actual exam
do
{
cout << "\nChoose your IP address:\n"; //It has you enter the server's
cout << "first numeral: "; //IP address one numeral at a time
cin >> ip1;
cout << "second numeral:";
cin >> ip2;
cout << "third numeral: ";
cin >> ip3;
cout << "fourth numeral:";
cin >> ip4;
cout << "\nIs this the server's IP address? [y/n]\n" << ip1 << "." << ip2 << "." << ip3 << "." << ip4 << endl;
cin >> yn; //this just shows the ip and ask for verification
}
while ( yn != 'y' && yn != 'Y' );

cout << "Enter your user name: ";
cin >> name;

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

if ( (top = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
{
cerr << "socket";
return 1;
}

them.sin_family=AF_INET;
them.sin_port=htons(PORT);
them.sin_addr.S_un.S_un_b.s_b1 = ip1;
them.sin_addr.S_un.S_un_b.s_b2 = ip2;
them.sin_addr.S_un.S_un_b.s_b3 = ip3;
them.sin_addr.S_un.S_un_b.s_b4 = ip4;
memset( &(them.sin_zero), '\0', 8); // Zero out rest of the structure

if (connect(top, (struct sockaddr *)&them, sizeof(struct sockaddr)) == -1)
{
cerr << "connect";
return 0;
}

FD_SET(top, &master);
fdmax = top+1;

cout << "Sending Screen Name" << endl;
if ( send( top, name, strlen(name), 0) == -1 )
{
cerr << "send";
return 1;
}
cout << "Name Sent" << endl;

//Main Loop
while(1)
{
readfds = master;
writefds = master;
if (select( fdmax, &readfds, &writefds, NULL, NULL) < 0)
{
cerr << "select";
return 1;
}

// Run through the main fun house
for ( int i = 0; i < fdmax; i++ )
{
if (FD_ISSET(top, &readfds))
{
if ( recv(top, rec, sizeof(buf), 0) == -1)
{
cout << "Server disconnected." << endl;
return 0;
}
else
{
for (unsigned int i=0; i < strlen(rec); i++ )
cout << rec[i];
}
}
cout << ": ";
cin.getline( buf, LENGTH, '\n');
len = strlen(buf);
if ( len > LENGTH ) // Prevent the user from entering a message that is to big
cout << "The string is to long" << endl;
else
{
if (FD_ISSET(top, &writefds))
{
if (cl.quitme( buf ) == 1 )
{
if ( send( top, buf, strlen(name), 0) == -1 )
{
cout << "Send upon user exit" << endl;
return 1;
}
closesocket(top);
cout << "Goodbye" << endl;
return 0;
}
else
{
if ( send( top, buf, strlen(name), 0) == -1 )
{
cout << "Send upon no user exit" << endl;
return 1;
}
}
}
}
}
}
closesocket(top);
return 0;
}


The first for loop within the while is not needed but there b/c i thought it might solve something. If you all headers and the server source are needed for you to help me then email me at bluedevils31@triad.rr.com and ask.

RobSeace
05-21-2003, 10:53 PM
I see several questionable things in that code... But, the ones
that I think may be leading to real problems are:


if ( send( top, buf, strlen(name), 0) == -1 )


for (unsigned int i=0; i < strlen(rec); i++ )


The first one is doing "strlen(name)", but sending "buf"...
The second one is assuming "rec" is null-terminated by
doing strlen() on it, but it most probably isn't, because recv()
sure doesn't null-terminate!

That may not be the cause of the problem you're seeing; I don't
know... It might be something in the server, too...

tal0n
05-21-2003, 11:13 PM
This is the server.

#include "list.h"
#include "tal0n_.h"
#include <stdlib.h>
#define port 9090
#define LENGTH 1500
#define len 20
#define BACKLOG 15

struct sockaddr_in server;
struct sockaddr_in client;
fd_set readfds, master;

int main()
{
int fdmax;
int sock, newfd, sockets[BACKLOG], count = 0;
WSADATA info;
tal0n_ serv;
char *buf;
char userName[len], name[len];
LINK first = NULL;

// Allocate memory for the four needed buffers
buf = (char *)malloc(sizeof(char[LENGTH]));

// Make sure we have enough memory
if ( (buf==0) )
{
cout << "Not enough memory for the buffer." << endl;
return 0;
}
if( WSAStartup(MAKEWORD(1, 1), &info) != 0 )
{
cout << "WSAStartup Problem" << endl;
return 0;
}

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

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
{
cout << "Socket failed";
return 0;
}

server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
memset(&(server.sin_zero), '\0', 8);

if ( bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1 )
{
cout << "Error in Bind" << endl;
return 0;
}

if ( listen( sock, BACKLOG ) == -1 )
{
cout << "Error in listen" << endl;
return 0;
}

FD_SET(sock, &master);
fdmax = sock;
freel();
cout << "Running..." << endl;

while(1)
{
readfds = master;
if ( select(fdmax+1, &readfds, NULL, NULL, NULL ) == -1 )
{
cout << "Error in select" << endl;
return 0;
}

for (int i=0; i <= fdmax; i++ )
{
if( FD_ISSET(i, &readfds) )
{
if ( i == sock )
{
int Wait = -2;
int sin_size = sizeof(struct sockaddr_in);
if( (newfd = accept( sock, (struct sockaddr *)&client, &sin_size)) == -1 )
{
cout << "Error in accept" << endl;
return 0;
}

sockets[count] = i;
FD_SET(newfd, &master);
fdmax = (newfd > fdmax) ? newfd : fdmax;

cout << endl << "Waiting for his/her screen name" << endl;
if ( (Wait = recv(newfd, name, 20, 0)==0) )
{
cout << "Connection closed at the other end!" << endl;
cout << "Closing. . ." << endl;
closesocket( i );
break;
}
else
{
cout << "Screen Name Acquired: " << name << "." << endl;
newuser( i, name, &client, first );
}
cout << "Connection recieved from " << inet_ntoa(client.sin_addr)
<< " on " << i << endl;
}
else
{
if ( recv( newfd, buf, LENGTH, 0) <= 0 )
{
cerr << "The client has disconnected or there is an error with recv" << endl;
FD_CLR((unsigned int)i, &master);
closesocket( i );
}
else
{
for( int l=0; l <= fdmax; l++ )
{
if ( FD_ISSET( l, &master) )
{
if ( (l != sock) )
{
getuser( userName, serv.getIp( i, &client ), first );
strcat( userName, ": " );
strcat( userName, buf );
if ( send( l, userName, strlen(userName), 0 ) == -1)
cout << "SenD" << endl;
}
}
}
}
}
}
}
}
return 0;
}

RobSeace
05-22-2003, 12:36 PM
if ( recv( newfd, buf, LENGTH, 0) <= 0 )


That's wrong... "newfd" isn't set to anything sensible at the point
you do that recv()... You want to use "i" as your FD, there...

Also, in the section where you're accept()'ing new clients, you
make what I believe are faulty references to "i", when in fact
THOSE should use "newfd", instead... Eg:


sockets[count] = i;
...
closesocket( i );
...
newuser( i, name, &client, first );

tal0n
05-23-2003, 03:41 AM
Ok the newuser function is not working properly. Everytime that a person connects the getpeername function is supposed to help me in getting their IP but evertime that someone connects I get the "invalid client: 0" message and then it crashes.

// Add a newly connected person to the list
void newuser( int sockfd, char tmp[big], struct sockaddr_in *info, LINK first )
{
char *ip;
int sin_size = sizeof( *info );

if( getpeername( sockfd, ( struct sockaddr *)&info, &sin_size ) == -1 )
cout << "Invalid client: " << errno << endl;
else
{
ip = inet_ntoa( info->sin_addr );
adduser( ip, tmp, first );
}
}

// You may need to look at this function to which puts the name and ip in
// the list
// Add user to the linked list
void adduser(char *ipaddr, char username[big], LINK first)
{
LINK newE;
LINK tmp;
LINK prev;

if ( (newE = (LINK)malloc(sizeof(LIST))) == NULL)
{
cout << "Not enough memory";
exit(0);
}

strcpy(newE->ip, ipaddr);
strcpy(newE->user, username);

if ( first == NULL )
{
first=newE;
newE->next=NULL;
}
else
{
tmp = first->next;
prev=first;
while( tmp->next != NULL )
{
newE->next = tmp;
if (newE->next != prev->next)
{
cout << "ERROR";
exit(0);
}
prev->next = newE;

}
if (tmp->next == NULL )
{
tmp->next = newE;
newE->next = NULL;
}
}
}

RobSeace
05-23-2003, 11:29 AM
void newuser( int sockfd, char tmp[big], struct sockaddr_in *info, LINK first )
{
char *ip;
int sin_size = sizeof( *info );

if( getpeername( sockfd, ( struct sockaddr *)&info, &sin_size ) == -1 )
cout << "Invalid client: " << errno << endl;
else
{
ip = inet_ntoa( info->sin_addr );
adduser( ip, tmp, first );
}
}


You're already passing in "info" as a pointer, so don't pass "&info"
to getpeername(); just pass "info"! (As for why errno is 0 in that
case, I don't know... But, based on some of your other code, I'd
guess you're working under Windoze, yes? If so, I believe I've
heard that that's just one more way that Windoze continues to
wallow in its non-standard suckiness: instead of setting errno
for socket stuff, it sets some other wacky code, which you have
to call some special function to get at... No, I'm not really sure
what it is, since I don't do ANY Windoze coding at all, thank god...)