3

In Python using the threading module, my program will not run the 2 threads I created simultaneously. I am trying to create an instant message program using P2P, and I don't know if the problem is to do with the socket module or I am doing something wrong. Code:

import socket
import threading

class Receiver:
    def __init__(self):

        # Create socket that supports IPv4, TCP Protocol
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        print "Socket created."
        # Requests for IP of host (DNS)
        dns = "localhost"
        HOST = ''
        PORT = 57492
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind((HOST, PORT)) # Listens on all interfaces...
        print 'Listening on port 25565'
        s.listen(True) # Listen on the newly created socket... 
        conn, addr = s.accept()
        print 'Connected in port 25565'
        global data
        while 1:
            data = conn.recv(1024)
            print data
        s.close()

    def Sender(self):

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        dns = "localhost"
        HOST = socket.gethostbyname(dns)
        PORT = 57492    
        # Connect to server
        s.connect((HOST, PORT))

        print "Socket connected to " + dns + " on IP " + HOST

        while 1:

            # Assign message to be sent to server to a variable
            message = raw_input("Message to be sent to server: ")

            #Send the actual message to server
            s.sendall(message)
        print "Message sent successfully"
        s.close()
    def go(self):

        th1 = threading.Thread()
        th2 = threading.Thread(target=self.Sender)
        th1.start()
        th2.start()

t = Receiver()
t.go()
spider93286
  • 57
  • 1
  • 6
  • what are you expecting `th1` to do? You didn't give it a `target` so it dies immediately after you create it. – roippi Apr 07 '14 at 00:20

3 Answers3

1

There are two problems here. First, th1 is never given a method to execute, and so when you call start on it, the thread does nothing and exits immediately. The second problem is that you're doing permanent work (an infinite while loop) inside the constructor of the Receiver class. That means that the line t = Receiver() will (basically) never return, and you'll never get to call go().

Here's an example, with all the socket stuff removed, of how to start two threads in basic framework you've setup:

#!/usr/bin/python

import threading
import time
import signal

class Communicator:
    def __init__(self):
        self.__stop = False

    def __runSender(self):
        # setup sender here
        while not self.__stop:
            # run sender loop here
            print "in sender"
            time.sleep(1)
        print "stopped sender"

    def __runReceiver(self):
        # setup receiver here
        while not self.__stop:
            # run recevier loop here
            print "in receiver"
            time.sleep(1)
        print "stopped receiver"

    def start(self):
        senderThread = threading.Thread(target=self.__runSender)
        receiverThread = threading.Thread(target=self.__runReceiver)
        senderThread.start()
        receiverThread.start()
    def stop(self):
        self.__stop = True


c = Communicator()

def handleKill(n, frame):
    print "HANDLING SIGNAL"
    c.stop()

signal.signal(signal.SIGINT, handleKill)
print "Starting communication, hit CTRL-c to stop"
c.start()
signal.pause()
gsteff
  • 4,764
  • 1
  • 20
  • 17
0

The Sender and go methods aren't indented and therefore not part of Receiver which means that when you define th2 there is no self.Sender.

  • Sorry, that was my fault. I forgot to indent the code while typing the question. I edited it, this is the real code. – spider93286 Apr 07 '14 at 00:11
0

These lines:

th1 = threading.Thread()
th2 = threading.Thread(target=self.Sender)

th1 has no operations to run.

Another point of concern is that you have a global variable data, and if you really plan to run this whole class multiple times, your multiple threads are probably going to clobber that variable and give you junk results. Or, were you planning to run Sender and Receiver simultaneously? The answer there with what you have is to probably pass th1 the parameter of target=self, but that seems like a terrible way to run a threaded application (a thread inside a thread?).

If the latter, you are probably better off separating Sender and Receiver into separate methods and setting up your threads to target these separate methods:

class Conversation:
    def __init__(self):
        pass

    def receiver(self):
        ...code code code...

    def sender(self):
        ...code code code...

    def go(self):

        th1 = threading.Thread(target=self.receiver)
        th2 = threading.Thread(target=self.render)
        th1.start()
        th2.start()

I don't know if this would completely solve your problem, but it's a start: it makes it so that th1 has something to do.

I also think you're also going to need some thread-safe way to tell your loops to end.

Lastly, keep you in mind you won't be able to safely pass data back and forth between these threads (if that's your intention) with the code as it currently stands.

erewok
  • 7,555
  • 3
  • 33
  • 45