Included below is the code that I am currently using:
soc1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ADDR = (HOST,PORT)
soc1.connect(ADDR)
soc1.send('WILL SEND')
The error message that I receive when running the above code is:
Traceback (most recent call last):
File "C:\workspace\wx_python_test\chat_server.py", line 25, in <module>
soc1.connect(ADDR)
File "C:\Python27\lib\socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 10061]
Could anyone please explain what the issue is that I am experiencing and how I can correct it?
Full source code: http://pastie.org/4245314
socket.error: [Errno 10061] indicates that the port you are trying to connect to is not open. You need to make sure that the port is open and something is listening for your connection to be made.
It appears that you are trying to test a chat server. In order for the chat server to work properly you will want to make sure that it is currently listening on the specified port.
Twisted provides a good framework if you haven't checked it out previously.
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
class Chat(LineReceiver):
def __init__(self, users):
self.users = users
self.name = None
self.state = "GETNAME"
def connectionMade(self):
self.sendLine("What's your name?")
def connectionLost(self, reason):
if self.users.has_key(self.name):
del self.users[self.name]
def lineReceived(self, line):
if self.state == "GETNAME":
self.handle_GETNAME(line)
else:
self.handle_CHAT(line)
def handle_GETNAME(self, name):
if self.users.has_key(name):
self.sendLine("Name taken, please choose another.")
return
self.sendLine("Welcome, %s!" % (name,))
self.name = name
self.users[name] = self
self.state = "CHAT"
def handle_CHAT(self, message):
message = "<%s> %s" % (self.name, message)
for name, protocol in self.users.iteritems():
if ':' in message:
self.exc(message.split(':')[0])
if protocol != self:
protocol.sendLine(message)
def exc(self, cmd):
print cmd
if cmd == 'who':
for i in self.users:
print i
class ChatFactory(Factory):
def __init__(self):
self.users = {} # maps user names to Chat instances
def buildProtocol(self, addr):
return Chat(self.users)
reactor.listenTCP(8123, ChatFactory())
reactor.run()
Your python is fine - check your network config and that you can actually connect to the specified host/port. You are getting Windows socket error 10061 - this is defined below:.
WSAECONNREFUSED 10061 Connection refused. No connection could be made
because the target computer actively refused it. This usually results
from trying to connect to a service that is inactive on the foreign
host—that is, one with no server application running.
Try doing telnet host port from your terminal window - and see if you can connect. If not, resolve the network issue first.
Related
My websocket client is trying to talk to a remote wss server, and is failing with this output:
[my-user#my-server]$ python my_websocket_client.py
ws-client connecting...
[Errno 111] Connection refused
conn closed
exception in main: 'NoneType' object has no attribute 'status'
ws-client connect status is not ok.
trying to reconnect
ws-client connecting...
[Errno 111] Connection refused
conn closed
exception in main 'NoneType' object has no attribute 'status'
...and it just repeats that over and over.
Here's the relevant code (client side):
def on_error(ws, error):
logger.error("on error is: %s" % error)
def reconnect():
global reconnect_count
logger.warning("ws-client connect status is not ok.\ntrying to reconnect for the %d time" % reconnect_count)
reconnect_count += 1
if reconnect_count < RECONNECT_MAX_TIMES:
thread.start_new_thread(connect, ())
def on_message(ws, message):
message_json = json.loads(message)
payload = base64_decode_as_string(message_json["payload"])
# handler payload
try:
message_handler(payload)
except Exception as e:
logger.error("handler message, a business exception has occurred,e:%s" % e)
send_ack(message_json["messageId"])
def on_close(obj):
logging.critical("Connection closed!")
obj.close()
global connect_status
connect_status = 0
def connect():
logger.info("ws-client connecting...")
ws.run_forever(sslopt=SSL_OPT, ping_interval=PING_INTERVAL_SECONDS, ping_timeout=PING_TIMEOUT_SECONDS)
def send_ack(message_id):
json_str = json.dumps({"messageId": message_id})
ws.send(json_str)
def main():
header = {"Connection": "Upgrade",
"username": ACCESS_ID,
"password": gen_pwd()}
websocket.setdefaulttimeout(CONNECT_TIMEOUT_SECONDS)
global ws
ws = websocket.WebSocketApp(get_topic_url(),
header=header,
on_message=on_message,
on_error=on_error,
on_close=on_close)
thread.start_new_thread(connect, ())
while True:
time.sleep(CHECK_INTERVAL_SECONDS)
global reconnect_count
global connect_status
try:
if ws.sock.status == 101:
# annoying
# print("ws-client connect status is ok.")
reconnect_count = 1
connect_status = 1
except Exception:
connect_status = 0
reconnect()
if __name__ == '__main__':
main()
Also, ws.sock is None.
The reason, I think, is because the server is trying to make a connection back to the client to a high port number; however, only a few ports like 80, 443 are available to reach back to the client.
I see in my code it uses run_forever. The documentation says this function has arguments for proxies, but the documentation doesn't give an overview of that process, isn't clear how to make that happen, and doesn't show what that looks like conceptually.
How can I make the server send messages to a proxy on port 443, which in turn talks to my websocket client, to help it overcome the unavailability of other port numbers?
Or, even better, how can I make the client tell the server to connect back to it only on port 443?
Note: I'm asking the question because there are conceptual things I don't understand and aren't clear in any of the available documentation. If it was, I wouldn't be asking.
The server administrator had to open up the port.
He opened up the port the client was connecting to, say 1234. This was surprising because I thought the WS server connected back to the client on a random high port. Either he opened up an outgoing port or WS has the server try the same port number. I don't know, but that's what fixed it.
import asyncore
class HTTPClient(asyncore.dispatcher):
def __init__(self, host, path):
asyncore.dispatcher.__init__(self)
self.create_socket()
self.connect( (host, 80) )
self.buffer = bytes('GET %s HTTP/1.0\r\nHost: %s\r\n\r\n' %
(path, host), 'ascii')
def handle_connect(self):
pass
def handle_close(self):
self.close()
def handle_read(self):
print(self.recv(8192))
def writable(self):
return (len(self.buffer) > 0)
def handle_write(self):
sent = self.send(self.buffer)
self.buffer = self.buffer[sent:]
client = HTTPClient('www.bocaonews.com.br', '/')
asyncore.loop()
And an error was raised:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "***.py", line 15, in __init__
self.connect( (host, 80) )
File "***\lib\asyncore.py", line 339, in connect
err = self.socket.connect_ex(address)
socket.gaierror: [Errno 11004] getaddrinfo failed
The HTTP client is the example of the official documentation. The error was raised because the host www.bocaonews.com.br is not accessible.
So my question is how to modify the code to let a client automatically close the connection when the host is bad? I can examine the host before generating the dispatcher. But it is less efficient.
asyncore doesn't offer much in the way of simplified error handling. Mostly, it leaves you responsible for this. So the solution is to add error handling to your application code:
try:
client = HTTPClient('www.bocaonews.com.br', '/')
except socket.error as e:
print 'Could not contact www.bocaonews.com.br:', e
else:
asyncore.loop()
To make your life a little easier, you may not want to call connect inside HTTPClient.__init__.
Also, for comparison, here's a Twisted-based HTTP/1.1 client:
from twisted.internet import reactor
from twisted.web.client import Agent
a = Agent(reactor)
getting = a.request(b"GET", b"http://www.bocaonews.com.br/")
def got(response):
...
def failed(reason):
print 'Request failed:', reason.getErrorMessage()
getting.addCallbacks(got, failed)
reactor.run()
I have set up a TCP server using the twisted example (with some modifications).
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
from os import path
import yaml
class User(LineReceiver):
def __init__(self,users):
self.users = users
self.name = None
def connectionMade(self):
print 'new connection'
self.sendLine('username:')
def connectionLost(self,reason):
print 'connection lost'
if not self.name == None:
msg = '%s has disconnected' % (self.name)
print msg
self.toAll(msg,None)
del self.users[self.name]
def lineRecieved(self,line):
print line
if self.name == None:
self.setName(line)
else:
self.toChat(line)
def toAll(self,msg,to_self):
for name, protocol in self.users.iteritems():
if protocol == self and not to_self == None:
self.sendLine(to_self)
else:
protocol.sendLine(msg)
def setName(self,name):
if self.users.has_key(name):
self.sendLine('username in use')
return
elif ' ' in name:
self.sendLine('no spaces!')
return
print 'new user %s' % (name)
self.sendLine('logged in as %s' % (name))
self.name = name
self.users[name] = self
def toChat(self,message):
msg = '<%s> %s' % (self.name,message)
print msg
to_self = '<%s (you)> %s' % (self.name,message)
self.toAll(msg,to_self)
class Main(Factory):
def __init__(self,motd=None):
self.users = {}
self.motd = motd
print 'loaded, waiting for connections...'
def buildProtocol(self,addr):
return User(self.users)
if not path.isfile('config.yml'):
open('config.yml','w').write('port: 4444\nmotd: don\'t spam')
with open('config.yml','r') as f:
dump = yaml.load(f.read())
motd = dump['motd']
port = dump['port']
reactor.listenTCP(port,Main(motd=motd))
reactor.run()
I was wondering how I would be able to connect to it? I've tried adapting their example Echo client and Echo server, but my server only gives a giant error when data is sent back to it.
(The echo server is here and the echo client is here)
The client I am using is
from twisted.internet import reactor
from twisted.internet.protocol import Protocol,ClientFactory
class Main(Protocol):
def dataReceived(self,data):
print data
self.transport.write(data)
class MainFactory(ClientFactory):
def buildProtocol(self,addr):
print 'connected'
return Main()
def clientConnectionLost(self,connector,reason):
print 'connection lost'
def clientConnectionFailed(self,connector,reason):
print 'connection failed'
reactor.connectTCP('localhost',4444,MainFactory())
reactor.run()
Here is a picture of the error
What do I need to do to send data back to the server? What class do I need to inherit from?
The problem is a simple typo.
LineReceiver calls its lineReceived method on each line. You're supposed to override that. But you don't, you define lineRecieved instead. So, you get the default implementation, which raises NotImplemented.
If you fix that, your code is still more than a little odd. Trace through the communication.
The client connects, which calls the server's User.connectionMade, which does this:
self.sendLine('username:')
So the client gets that in Main.dataReceived and does this:
self.transport.write(data)
So, it's sending the prompt back as a response.
The server will receive that in lineReceived (once you fix the name) and do this:
if self.name == None:
self.setName(line)
So, you're going to set the username to 'username:'.
I'm writing an asyncore server which fetches info from another module in same process and writes it back to client. The info basically is a dictionary where for each key we have a queue of messages. I'm required to dump the length of each queue. The code runs fine on a test machine but as soon as I install it on a production server I start getting following error message : "socket.error'>:[Errno 32] Broken pipe)".
This is the server:
class request_handler (asyncore.dispatcher):
def __init__(self, conn_sock, client_address, dict):
self.client_address = client_address
self.buffer = ""
self.dict = dict
asyncore.dispatcher.__init__(self, conn_sock)
def readable(self):
return True
def writable(self):
return False
def handle_read(self):
data = self.recv(SIZE)
mtats = "msgq-stats"
if data:
buffer = data
if buffer.lower() == mstats.lower():
msgout = "-- Message Queue Stats --\n"
for key, value in dict.items():
mq = 0
if dict[key].message_queue:
mq = len(dict[key].message_queue)
msgout += key + ":" + str(mq) + "\n"
self.send(msgout)
else: self.send("Invalid input\n")
else:
self.send("Invalid input\n")
def handle_write(self):
print ("--Handling read--\n")
def handle_close(self):
pass
# ---------------------------------------------------------------------
class monitor_server (asyncore.dispatcher):
def __init__ (self, ip, port, destination):
sys.path.append('/path/')
import dict
self.ip = ip
self.port = port
self.dict = dict
asyncore.dispatcher.__init__ (self)
self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind ((ip, port))
self.listen (5)
def writable (self):
return 0
def handle_read (self):
pass
def readable (self):
return self.accepting
def handle_connect (self):
pass
def handle_accept (self):
(conn_sock, client_address) = self.accept()
request_handler (conn_sock, client_address, self.destination)
and this is the client code:
class Client(asyncore.dispatcher_with_send):
def __init__(self, host, port, message):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
print "Message being sent is "
print message
self.out_buffer = message
def handle_close(self):
self.close()
def handle_read(self):
print self.recv(1024)
self.close()
c = Client('', 6000, 'msgq-stats')
asyncore.loop()
Thanks in advance.
That's an error case you have to handle. Sometimes connections will close. It's normal for different socket errors to be encountered during development as compared to in production, since there are so many different possible errors and they almost entirely depend on the execution environment and what the program on the other side of the connection is doing and on what all the routers between the client and the server decide to do.
So, the literal answer to your question is that you need to handle this and many other socket errors in your application code. That's part of your job when you use asyncore. Add the necessary exception handling and mark the connection as closed when something like this happens.
A slightly better answer is that there are higher level tools that make network programming easier, and you should probably consider using those. The big thing in this area is Twisted.
I've got a problem with setting up a client which connects to a "distributor" server to send certain data.
The server's purpose is to get data from the client and then send that data to it's all connected clients. The server works without any issues.
The main client is also supposed to work as an IRC bot.
Here's a text example of how it should work like:
(IRC) John: Hello there!
1. The IRC client got the message, we need to send it to the distributor now.
2. Distributor should get this "John: Hello there!" string and send it back to it's all connected clients.
3. If other clients send data to the distributor, which this will broadcast to all clients, the IRC client should output at it's turn the received data to a specified channel
The following code is the IRC bot client (ircbot.py):
import sys
import socket
import time
import traceback
from twisted.words.protocols import irc
from twisted.internet import reactor
from twisted.internet import protocol
VERBOSE = True
f = None
class IRCBot(irc.IRCClient):
def _get_nickname(self):
return self.factory.nickname
nickname = property(_get_nickname)
def signedOn(self):
self.msg("NickServ", "id <password_removed>") # Identify the bot
time.sleep(0.1) # Wait a little...
self.join(self.factory.channel) # Join channel #chantest
print "Signed on as %s." % (self.nickname,)
def joined(self, channel):
print "Joined %s." % (channel,)
def privmsg(self, user, channel, msg):
name = user.split('!', 1)[0]
prefix = "%s: %s" % (name, msg)
print prefix
if not user:
return
if self.nickname in msg:
msg = re.compile(self.nickname + "[:,]* ?", re.I).sub('', msg)
print msg
else:
prefix = ''
if msg.startswith("!"):
if name.lower() == "longdouble":
self.msg(channel, "Owner command") # etc just testing stuff
else:
self.msg(channel, "Command")
if channel == "#testchan" and name != "BotName":
EchoClient().sendData('IRC:'+' '.join(map(str, [name, msg])))
# This should make the bot send chat data to the distributor server (NOT IRC server)
def irc_NICK(self, prefix, params):
"""Called when an IRC user changes their nickname."""
old_nick = prefix.split('!')[0]
new_nick = params[0]
self.msg(, "%s is now known as %s" % (old_nick, new_nick))
def alterCollidedNick(self, nickname):
return nickname + '1'
class BotFactory(protocol.ClientFactory):
protocol = IRCBot
def __init__(self, channel, nickname='BotName'):
self.channel = channel
self.nickname = nickname
def clientConnectionLost(self, connector, reason):
print "Lost connection (%s), reconnecting." % (reason,)
connector.connect()
def clientConnectionFailed(self, connector, reason):
print "Could not connect: %s" % (reason,)
class EchoClient(protocol.Protocol):
def connectionMade(self):
pass
def sendData(self, data):
self.transport.write(data)
def dataReceived(self, data):
if VERBOSE:
print "RECV:", data
IRC.msg("#chantest", data)
#This one should send the received data from the distributor to the IRC channel
def connectionLost(self, reason):
print "Connection was lost."
class EchoFactory(protocol.ClientFactory):
def startedConnecting(self, connector):
print 'Started to connect.'
def buildProtocol(self, addr):
print 'Connected to the Distributor'
return EchoClient()
def clientConnectionFailed(self, connector, reason):
print "Cannot connect to distributor! Check all settings!"
reactor.stop()
def clientConnectionLost(self, connector, reason):
print "Distributor Lost connection!!"
reactor.stop()
if __name__ == "__main__":
IRC = BotFactory('#chantest')
reactor.connectTCP('irc.rizon.net', 6667, IRC) # Our IRC connection
f = EchoFactory()
reactor.connectTCP("localhost", 8000, f) # Connection to the Distributor server
reactor.run()
The following code is the distributor server (distributor.py):
(This one works fine, but maybe it could be useful for further reference)
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
class MultiEcho(Protocol):
def __init__(self, factory):
self.factory = factory
def connectionMade(self):
print "Client connected:",self
self.factory.echoers.append(self)
self.factory.clients = self.factory.clients+1
#self.transport.write("Welcome to the server! There are currently "+`self.factory.clients`+" clients connected.")
def dataReceived(self, data):
print "RECV:",data
for echoer in self.factory.echoers:
echoer.transport.write(data)
def connectionLost(self, reason):
print "Client disconnected:",self
self.factory.echoers.remove(self)
self.factory.clients = self.factory.clients-1
class MultiEchoFactory(Factory):
def __init__(self):
self.clients = 0
self.names = []
self.echoers = []
def buildProtocol(self, addr):
return MultiEcho(self)
if __name__ == '__main__':
print "Running..."
reactor.listenTCP(8000, MultiEchoFactory())
reactor.run()
I want the client to output all incoming chat data from the IRC server to the "distributor" server and also output incoming data from the "distributor".
However, I get errors like this:
For the following line in ircbot.py,
EchoClient().sendData('IRC'+' '.join(map(str, [name, msg])))
I get the following error:
Joined #chantest.
Longdouble: test
Traceback (most recent call last):
File "C:\Python\lib\site-packages\twisted\internet\tcp.py", line 460, in doRea
d
return self.protocol.dataReceived(data)
File "C:\Python\lib\site-packages\twisted\words\protocols\irc.py", line 2277,
in dataReceived
basic.LineReceiver.dataReceived(self, data.replace('\r', ''))
File "C:\Python\lib\site-packages\twisted\protocols\basic.py", line 564, in da
taReceived
why = self.lineReceived(line)
File "C:\Python\lib\site-packages\twisted\words\protocols\irc.py", line 2285,
in lineReceived
self.handleCommand(command, prefix, params)
--- <exception caught here> ---
File "C:\Python\lib\site-packages\twisted\words\protocols\irc.py", line 2329,
in handleCommand
method(prefix, params)
File "C:\Python\lib\site-packages\twisted\words\protocols\irc.py", line 1813,
in irc_PRIVMSG
self.privmsg(user, channel, message)
File "C:\Python\Traance\kwlbot\ircbot.py", line 51, in privmsg
EchoClient().sendData('IRC'+' '.join(map(str, [name, msg])))
File "C:\Python\Traance\kwlbot\ircbot.py", line 90, in sendData
self.transport.write(data)
exceptions.AttributeError: 'NoneType' object has no attribute 'write'
And same goes to this line in the same ircbot.py
IRC.msg("#chantest", data)
->
RECV: Hello from Distributor Server
Traceback (most recent call last):
File "C:\Python\Traance\kwlbot\ircbot.py", line 96, in dataReceived
IRC.msg("#chantest", data)
AttributeError: BotFactory instance has no attribute 'msg'
What am I doing wrong? How can I call the right function from the IRCbot class to make it send the data to the distributor server and data received from the distributor server to output in the specified channel via IRC?
Any suggestions and possible solutions are welcome.
If I missed any other details, please let me know.
Thank you for your time!
You should avoid writing blocking code like this:
def signedOn(self):
self.msg("NickServ", "id <password_removed>") # Identify the bot
time.sleep(0.1) # Wait a little...
self.join(self.factory.channel) # Join channel #chantest
print "Signed on as %s." % (self.nickname,)
For details, see Tail -f log on server, process data, then serve to client via twisted.
Apart from that, the main problem here is that you are trying to send data without having a connection. When you write something like:
EchoClient().sendData('IRC'+' '.join(map(str, [name, msg])))
you're creating a protocol instance which is responsible for handling a connection and then trying to use it, but you're not creating a connection. The attempt to send data fails because the protocol hasn't been attached to any transport.
Your snippet already demonstrates the correct way to create a connection, twice in fact:
IRC = BotFactory('#chantest')
reactor.connectTCP('irc.rizon.net', 6667, IRC) # Our IRC connection
f = EchoFactory()
reactor.connectTCP("localhost", 8000, f) # Connection to the Distributor server
The mistake is creating a new EchoClient instance, one with no connection. The reactor.connectTCP call creates a new connection and a new EchoClient instance and associates them with each other.
Instead of EchoClient().sendData(...), you want to use the EchoClient instance created by your factory:
def buildProtocol(self, addr):
print 'Connected to the Distributor'
return EchoClient()
Your buildProtocol implementation creates the instance, all that's missing is for it to save the instance so it can be used by your IRC bot.
Consider something like this:
def buildProtocol(self, addr):
print 'Connected to the Distributor'
self.connection = EchoClient()
return self.connection
Your IRC client can then use the saved EchoClient instance:
if channel == "#testchan" and name != "BotName":
f.connection.sendData('IRC:'+' '.join(map(str, [name, msg])))
# This should make the bot send chat data to the distributor server (NOT IRC server)
Note that the specific code I give here is a very crude approach. It uses the global variable f to find the EchoFactory instance. As with most global variable usage this makes the code a little hard to follow. Further, I haven't added any code to handle connectionLost events to clear the connection attribute out. This means you might think you're sending data to the distributed server when the connection has already been lost. And similarly, there's no guarantee that the connection to the distributed server will have been created by the time the IRC client first tries to use it, so you may have an AttributeError when it tries to use f.connection.sendData.
However, fixing these doesn't require much of a leap. Fix the global variable usage as you would any other - by passing arguments to functions, saving objects as references on other objects, etc. Fix the possible AttributeError by handling it, or by not creating the IRC connection until after you've created the distributed connection, etc. And handle lost connections by resetting the attribute value to None or some other sentinel, and paying attention to such a case in the IRC code before trying to use the distributed client connection to send any data.
TFM is never defined in your code, so I don't know what the deal is there.
The other error is that you're instantiating a client, but never connecting it to anything, as with reactor.connectTCP(...) or endpoint.connect(...). The transport attribute will be None until it's set by something.
(It would be helpful for you to come up with a simpler version of this code which is complete and doesn't include unnecessary details like all the printed log messages. It makes it harder to see what the real issues are.)