Welcome, guest | Sign In | My Account | Store | Cart

This took me longer than it should have. I am putting it here in the hopes that this post will spare others from having to Google things for extended periods of time.

In short, you either listen for a connection (Chat_Server), or connect to a remote IP address (Chat_Client). From there, you can send text strings back and forth.

This is a bit rough-hewn, obviously; I apologize in advance.

Python, 110 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!usr/bin/env python

import socket
import threading
import select
import time

def main():

    class Chat_Server(threading.Thread):
            def __init__(self):
                threading.Thread.__init__(self)
                self.running = 1
                self.conn = None
                self.addr = None
            def run(self):
                HOST = ''
                PORT = 1776
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                s.bind((HOST,PORT))
                s.listen(1)
                self.conn, self.addr = s.accept()
                # Select loop for listen
                while self.running == True:
                    inputready,outputready,exceptready \
                      = select.select ([self.conn],[self.conn],[])
                    for input_item in inputready:
                        # Handle sockets
                        data = self.conn.recv(1024)
                        if data:
                            print "Them: " + data
                        else:
                            break
                    time.sleep(0)
            def kill(self):
                self.running = 0
     
    class Chat_Client(threading.Thread):
            def __init__(self):
                threading.Thread.__init__(self)
                self.host = None
                self.sock = None
                self.running = 1
            def run(self):
                PORT = 1776
                self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.sock.connect((self.host, PORT))
                # Select loop for listen
                while self.running == True:
                    inputready,outputready,exceptready \
                      = select.select ([self.sock],[self.sock],[])
                    for input_item in inputready:
                        # Handle sockets
                        data = self.sock.recv(1024)
                        if data:
                            print "Them: " + data
                        else:
                            break
                    time.sleep(0)
            def kill(self):
                self.running = 0
                
    class Text_Input(threading.Thread):
            def __init__(self):
                threading.Thread.__init__(self)
                self.running = 1
            def run(self):
                while self.running == True:
                  text = raw_input('')
                  try:
                      chat_client.sock.sendall(text)
                  except:
                      Exception
                  try:
                      chat_server.conn.sendall(text)
                  except:
                      Exception
                  time.sleep(0)
            def kill(self):
                self.running = 0

    # Prompt, object instantiation, and threads start here.

    ip_addr = raw_input('What IP (or type listen)?: ')

    if ip_addr == 'listen':
        chat_server = Chat_Server()
        chat_client = Chat_Client()
        chat_server.start()
        text_input = Text_Input()
        text_input.start()
        
    elif ip_addr == 'Listen':
        chat_server = Chat_Server()
        chat_client = Chat_Client()
        chat_server.start()
        text_input = Text_Input()
        text_input.start()
        
    else:
        chat_server = Chat_Server()
        chat_client = Chat_Client()
        chat_client.host = ip_addr
        text_input = Text_Input()
        chat_client.start()
        text_input.start()

if __name__ == "__main__":
    main()



            

Defaults to port 1776, but can be changed fairly easily (note must be changed in two locations).

4 comments

Matthew Fisher 8 years, 4 months ago  # | flag

Looks great, teddy_k. May I suggest a few things to refine this?

  • make your PORT env variable global for this snippet, so that you only have to change it in one place.
  • there is a lot of redundant code that could be modularized. For example, both your chat server and client have lines that are the exact same, and could be placed into its own function called handle_sockets() or something, passing in inputready:

    for input_item in inputready:
        # Handle sockets
        data = self.conn.recv(1024)
        if data:
            print "Them: " + data
        else:
            break
    
  • you check for 'listen' and 'Listen', and repeat the same code twice. Why not just do an case insensitive string check?

  • the if statements should not have repeated code in both (seeing a pattern here?). I would move these lines outside of the conditionals so that it looks like this:

    # It gets initialized in both anyways, so why put it in an if statement?
    chat_server = Chat_Server()
    chat_client = Chat_Client()
    
    if ip_addr.lower() == 'listen': # case insensitive check
        chat_server.start()
    else:
        chat_client.host = ip_addr
        chat_client.start()
    
    text_input = Text_Input()
    text_input.start()
    
teddy_k (author) 8 years, 4 months ago  # | flag

Thank you for taking the time to reply, Matthew. I greatly appreciate the feedback.

Your observations are all correct; much of the code is redundant, the 'if' statements should be clearer, and a global variable would make changing the port simpler.

May I have permission to include your improvements in the above MIT-licensed code (with attribution, of course)? If not OK, I understand--I only ask because your changes would represent a significant improvement to what I cobbled together.

Thanks, teddy_k

Nick Farrow 7 years, 9 months ago  # | flag

I just wanted to see how it runs and get this error.

File "test.py", line 32 print "Them: " + data ^ SyntaxError: invalid syntax

Nick Farrow 7 years, 9 months ago  # | flag

Got it working looks like I was using 3.2 where the print statement has been changed. Works fine on 2.7. thanks for all your work teddy_k