Jump to content

Recommended Posts

Posted

I'm working on a simple python chat application:

http://paste.pound-python.org/show/9689/

But I'm having a few problems that I'll list below:

1) Say Bob and Sue are chatting, if Bob has typed out half a message and then Sue sends her message Sue's message gets appended to Bob's and a newline is creating, if Bob hits enter his half typed message is sent but the problem is it's not very visually appealing and can create quite a mess if someone would want to read back over their conversation. What I really want to do is every time a new message is received, get the value of stdin, clear stdin, print the new message, set stdin to value got earlier. Problem is I have yet to figure out a way to do this.

2) When using ctrl+c to quit it doesn't do a clean exit, you have to ctrl+c on both ends of the chat client before they both quit, not sure why. Any help would be appreciated! Thanks in advance.

Posted

I'm not all that great with python yet, but your second issue I'd imagine you just make it send a "Disconnect" message to the other computer and it exits the program. For example AT H0 for old dialup modems was the "Hang Up" command. On modem cards made prior to the year 2000 you can send the commands in a packet and it would respond. I used to use that to knock people off dialup when I got their IP addresses via P2P connection.

http://michaelgellis.tripod.com/modem.html

Not sure on the first issue you have. I could probably walk through the code and figure it out if I wasn't so tired and knew python a bit better.

Posted (edited)

That's really interesting with the modems. But no, I don't think that's the problem, the main loop of the program looks like this:

receive().start()
try:
	while 1:
		conn[s].send(raw_input())
except:
	print 'Disconnecting'
conn[s].close()
conn[r].close()

receive().start() begins the thread that receives and prints out messages and the other one is pretty self explanatory, it sends everything you type (raw_input() waits for the enter key so it just loops around), the except statement gets called if you ctrl+c out of the loop because a KeyboardInterrupt is considered an error, problem is it hangs on the 2 lines where it should be disconnecting, my only guess is it's waiting on some confirmation from the other client before disconnecting?

On a side note I just realized the except isn't really necessary so I'll probably eliminate that and yes, I will get around to coding some basic commands that let you disconnect properly without having to ctrl+c.

//edit

Here's what happens when I run the program and try to quit:

user@computer:~/chat-python$ ./pyCHAT.py 
Server(s) or Client(c) mode: c
Host address: 127.0.0.1
Port: 1212
sent -> Hello

With both the server and client successfully running I say "Hello" to the server.

user@computer:~/chat-python$ ./pyCHAT.py 
Server(s) or Client(c) mode: s
Port: 1212
received -> Hello

The server gets the "Hello" message just fine.

user@computer:~/chat-python$ ./pyCHAT.py 
Server(s) or Client(c) mode: s
Port: 1212
Hello
^CDisconnecting
^C

I press ctrl+c on the server (note, this same problem happens regardless of whether ctrl+c is pressed on the client or the server).

user@computer:~/chat-python$ ./pyCHAT.py 
Server(s) or Client(c) mode: c
Host address: 127.0.0.1
Port: 1212
Hello

The client shows nothing, doesn't know that the server is trying to disconnect (which is how it should look).

user@computer:~/chat-python$ ./pyCHAT.py 
Server(s) or Client(c) mode: c
Host address: 127.0.0.1
Port: 1212
Hello
^CDisconnecting
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "./pyCHAT.py", line 51, in run
    data = conn[r].recv(2048)
  File "/usr/lib/python2.7/socket.py", line 170, in _dummy
    raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor

user@computer:~/chat-python$ 

I press ctrl+c on the client, error is thrown and returns me to the command line.

user@computer:~/chat-python$ ./pyCHAT.py 
Server(s) or Client(c) mode: s
Port: 1212
Hello
^CDisconnecting
^CException in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "./pyCHAT.py", line 51, in run
    data = conn[r].recv(2048)
  File "/usr/lib/python2.7/socket.py", line 170, in _dummy
    raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor

Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored
user@computer:~/chat-python$ 

The server also throws an error and exits to the command line.

Edited by TehFallen
Posted

Maybe something simple, like just adding a new line, or line feed, every time each user sends a message, so they don't append each others message would work.

Also, instead of sending to the screen natively, why not write all output to a log file, then echo each new line, have the program listen on a port and just echo each new line to screen, whats being written to log, then you also have a way to read everything when the chat is over, and you don't lose the entire conversation.

Maybe add some debug stuff in the log file too, that isn't shown on the screen, like line numbering, time stamps, IP address for each username(so is always unique and knows where to send line feed, instead of just by user name, when they send, prefix line feed based on unique IP), and any errors, as well as certain key strokes(like ctrl+c) so if it does crash, you can dump it to the log file itself and see whats happening at that point. Just some ideas.

Posted

The problem with adding a new line is I wouldn't know when to do it and when not too, if "Bob" hasn't typed anything into stdin then I don't want to add a new line because it'd produce an out of place blank space and even if even "Bob" had typed part of something, receive a new message, and finished typing his message would be broke into two with the incoming message in between. The problem with python I'm seeing is all it's ways of collecting input rely on the user hitting enter when they're done and I want to be able to see what they've typed as they type it. I did just stumble upon a read() function though that reads a certain amount of characters from the stdin and think I might be able to turn off default echo-ing of keys and use this to read the last character typed, print it, add it to a string, etc etc, still a bit of overkill seeing as all I really need is some sort of read everything function and then clear stdin.

I didn't even think about a log but that's a great idea, I'll look into implementing that today at some point. Ideally I would like to have a gui with an input box and a simple text box that displays the conversation as I write out to it, which would actually solve all my input output problems :D

I'll look into the debug stuff too, I think I remember reading somewhere that you can redirect stderr to a file in python so the user doesn't get any of it live. Definitely worth a google. Thanks for all the suggestions!

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...