TCP-based chat program

This is a discussion on TCP-based chat program within the Programming Languages forums in category; I wrote a little UDP-based chat program. It's not very user-friendly, requiring every user to add every other user to a list. Anyway, I want to adapt it to TCP so you don't have to do that, as well as the ability to talk to people behind firewalls without reconfiguring them. The first problem I have is how to have the server application relay messages to all the clients. The other problem is how to format the output on the client application so that it can show what other people are saying as well as having a prompt at the ...

Go Back   Application Development Forum > Programming Languages

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 08-27-2008, 06:29 PM
phider1
Guest
 
Default TCP-based chat program

I wrote a little UDP-based chat program. It's not very user-friendly,
requiring every user to add every other user to a list. Anyway, I
want to adapt it to TCP so you don't have to do that, as well as the
ability to talk to people behind firewalls without reconfiguring them.
The first problem I have is how to have the server application relay
messages to all the clients. The other problem is how to format the
output on the client application so that it can show what other people
are saying as well as having a prompt at the bottom. Currently I have
2 seperate apps, one that listens for incoming messages, and one to
send messages, but I don't think that'd work with TCP.

The UDP app is available for DL here, if anyone is interested.
http://sodasphere.us.to/pub/yipee
Reply With Quote
  #2  
Old 08-27-2008, 08:23 PM
Richard Heathfield
Guest
 
Default Re: TCP-based chat program

phider1 said:

> I wrote a little UDP-based chat program. It's not very user-friendly,
> requiring every user to add every other user to a list. Anyway, I
> want to adapt it to TCP so you don't have to do that, as well as the
> ability to talk to people behind firewalls without reconfiguring them.
> The first problem I have is how to have the server application relay
> messages to all the clients. The other problem is how to format the
> output on the client application so that it can show what other people
> are saying as well as having a prompt at the bottom. Currently I have
> 2 seperate apps, one that listens for incoming messages, and one to
> send messages, but I don't think that'd work with TCP.


No doubt you'll get lots of complicated answers, and no doubt they'll be
good answers.

Me? I'm simple, me. I'd do it like this:

1) the server

In one way, this is simpler than the client, because you don't have to
worry about a GUI if you don't want to.

It is *not* my purpose here to teach you how to program TCP sockets in any
kind of detail; rather, I'll just touch on what I consider a nice simple
design that doesn't involve threads or anything scary like that.

Ingredients

(a) a listening socket
(b) two circular lists, LOGINLIST and CHATLIST

Method

do all the initialisation work for the listening socket
while not done
select on the listening socket, with a delay of 0 - it'll come
right back to you, telling you yay or nay

if there's an incoming connection request
create a new entry in the LOGINLIST, which will contain
the new socket for the connection, any login data, and
anything else you need to record for this user
endif

select on all the login sockets
for up to L entries in the LOGINLIST that have messages waiting
perform one step in your login protocol (e.g. get a user name,
or get a password, or reject a password, or whatever it is)
for this user, such that the /next/ step (if any) is up to the
user
if this step completes the login process
remove this item from LOGINLIST
add this item to CHATLIST
endif
rotate the list one place
endfor

select on all the chat sockets
for up to C entries in the CHATLIST that have messages waiting
receive the message from THISUSER
if this is a chat message
while the current user's *successor* is not THISUSER
send out the message to the current user in the CHATLIST
rotate the CHATLIST one place
endwhile
else
deal with the message as appropriate (eg PRIVMSG, LOGOFF,
or whatever)
endif
rotate the CHATLIST one place
endfor
endwhile

This is about as simple as it gets, and doesn't require you to have an
outlandish number of threads going - in fact, it's single-threaded and
non-blocking.

The "while not done" thing can be done using signal() to intercept Ctrl-C
and set a volatile sig_atomic_t to 1:

volatile sig_atomic_t done;

void term(int sig)
{
done = 1;
}

Register that function for handling SIGINTs, using signal().

Then your main loop is simply:

while(!done)
{
all that stuff I said
}

cleanup goes here - shutting down the listening socket, releasing
dynamically allocated memory, etc.



2) the client

The client is easier on the socket side, but harder on the interface side.
On Win32, the fast-n-dirty solution would be to use the console functions
(look up something like AllocConsole in MSDN, and then browse around that
family of functions - you should soon work it out). On Linux, probably
curses - or rather, ncurses.

If you can find an ncurses for Windows, you're laughing.

The point is that either of these techniques will allow you to address the
screen at a point of your choosing. This allows you to have a chat log
(typically a very large area) and a separate input zone (typically a
single line at the bottom), and the output messages won't have to choose
between waiting till you're done or corrupting your typing line. Some
clients also have other stuff in other screen areas - e.g. user name
lists, channel lists, etc.

The comms design is easy enough:

do the whole connection thing
while not done
select on the server socket
if there's a message waiting on the server
get the message
if it's a chat message
stick it in the chatlog zone
else
deal with it appropriately
endif
endif
if the user just typed a line
wrap it up as and if necessary, and send it to the server
clear the input zone
endif
endwhile
cleanup

Note: I took a quick look at your source to find out which platforms you're
interested in, and I saw this:

scanf("%s",name);

That is so 1988. Nowadays, we protect our buffers, by using a line-reading
buffer-protecting routine such as fgets, and then parsing it as necessary.
If you don't want to do that, at the very least you should tell scanf your
maximum buffer size, e.g. scanf("%11s", name); for your 12-byte buffer.

Note, too, that scanf will return the number of fields successfully
converted. If it's fewer than you asked for, that's obviously a problem,
and one that you can detect and correct for.

Incidentally, you have a WSACleanup call in your Linux send code. :-)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Reply With Quote
  #3  
Old 08-27-2008, 09:19 PM
phider1
Guest
 
Default Re: TCP-based chat program

gah... That's really long and complex. What if I were to say that my
server didn't require any sort of login? All it has to do is know
who's connected at the time and relay messages. It also needs to be
able to return a list of users (eg. when a user types /who or
something like that).
Reply With Quote
  #4  
Old 08-27-2008, 09:21 PM
phider1
Guest
 
Default Re: TCP-based chat program

> Note: I took a quick look at your source to find out which platforms you're
> interested in, and I saw this:
>
> * * * * scanf("%s",name);
>
> That is so 1988. Nowadays, we protect our buffers, by using a line-reading
> buffer-protecting routine such as fgets, and then parsing it as necessary..
> If you don't want to do that, at the very least you should tell scanf your
> maximum buffer size, e.g. scanf("%11s", name); for your 12-byte buffer.


Thanks. I've seen mention of scanf's maximum buffer size, but didn't
know the syntax.

> Incidentally, you have a WSACleanup call in your Linux send code. :-)


Oops... I'll go ahead and fix that now :P
Reply With Quote
  #5  
Old 08-27-2008, 09:42 PM
Richard Heathfield
Guest
 
Default Re: TCP-based chat program

phider1 said:

> gah... That's really long and complex.


No, it isn't - really!

> What if I were to say that my server didn't require any sort of login?


Then I'd say you're asking for trouble (unless you're on a LAN with no
Internet connectivity), and it would simply mean that the acceptance of
new users would be a little smoother (at least, until the crackers found
your server (unless you're on a LAN with no Internet connectivity)).

> All it has to do is know
> who's connected at the time


Yes - and the process of connecting is normally called "logging in".

> and relay messages. It also needs to be
> able to return a list of users (eg. when a user types /who or
> something like that).


That's one of the many uses for the CHATLIST circular list - you can easily
enquire it to find out who is logged... sorry! To find out who is
connected.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Reply With Quote
  #6  
Old 08-27-2008, 09:54 PM
phider1
Guest
 
Default Re: TCP-based chat program

Really, my plan for this program right now is just to give it to
friends and play around with it. Anyway, I'll try reading through it
again and see if I can understand it all...
Reply With Quote
  #7  
Old 10-19-2008, 12:47 PM
Ike Naar
Guest
 
Default Re: TCP-based chat program

In article <EbOdnbnRWPSEcijVnZ2dnUVZ8judnZ2d@bt.com>,
Richard Heathfield <rjh@see.sig.invalid> wrote:
>Note: I took a quick look at your source to find out which platforms you're
>interested in, and I saw this:
>
> scanf("%s",name);
>
>That is so 1988. Nowadays, we protect our buffers, by using a line-reading
>buffer-protecting routine such as fgets, and then parsing it as necessary.
>If you don't want to do that, at the very least you should tell scanf your
>maximum buffer size, e.g. scanf("%11s", name); for your 12-byte buffer.


That should be ``scanf("%.11s", name);'' (note the dot)
Reply With Quote
  #8  
Old 10-19-2008, 01:46 PM
Ike Naar
Guest
 
Default Re: TCP-based chat program

In article <1224434866.31958.0@proxy01.news.clara.net>,
Ike Naar <ike@localhost.claranet.nl> wrote:
>In article <EbOdnbnRWPSEcijVnZ2dnUVZ8judnZ2d@bt.com>,
>Richard Heathfield <rjh@see.sig.invalid> wrote:
>>Note: I took a quick look at your source to find out which platforms you're
>>interested in, and I saw this:
>>
>> scanf("%s",name);
>>
>>That is so 1988. Nowadays, we protect our buffers, by using a line-reading
>>buffer-protecting routine such as fgets, and then parsing it as necessary.
>>If you don't want to do that, at the very least you should tell scanf your
>>maximum buffer size, e.g. scanf("%11s", name); for your 12-byte buffer.

>
>That should be ``scanf("%.11s", name);'' (note the dot)


Whoops!

Actually, Richard was right. The dot should not be there.
(I was confusing scanf format conversion specifiers with those for printf)

Regards,
Ike
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 05:10 PM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.