I have been trying to test SCTP for a network deployment.
I do not have an SCTP server or client and was hoping to be able use pysctp.
I am fairly certain that I have the client side code working.
def sctp_client ():
print("SCTP client")
sock = sctp.sctpsocket_tcp(socket.AF_INET)
#sock.connect(('10.10.10.70',int(20003)))
sock.connect(('10.10.10.41',int(21000)))
print("Sending message")
sock.sctp_send(msg='allowed')
sock.shutdown(0)
sock.close()
Has anybody had luck with using the python sctp module for the server side?
Thank you in Advance!
I know that this topic's a bit dated, but I figured I would respond to it anyway to help out the community.
In a nutshell:
you are using pysctp with the sockets package to create either a client or a server;
you can therefore create your server connection as you normally would with a regular TCP connection.
Here's some code to get you started, it's a bit verbose, but it illustrates a full connection, sending, receiving, and closing the connection.
You can run it on your dev computer and then use a tool like ncat (nmap's implementation of netcat) to connect, i.e.: ncat --sctp localhost 80.
Without further ado, here's the code... HTH:
# Here are the packages that we need for our SCTP server
import socket
import sctp
from sctp import *
import threading
# Let's create a socket:
my_tcp_socket = sctpsocket_tcp(socket.AF_INET)
my_tcp_port = 80
# Here are a couple of parameters for the server
server_ip = "0.0.0.0"
backlog_conns = 3
# Let's set up a connection:
my_tcp_socket.events.clear()
my_tcp_socket.bind((server_ip, my_tcp_port))
my_tcp_socket.listen(backlog_conns)
# Here's a method for handling a connection:
def handle_client(client_socket):
client_socket.send("Howdy! What's your name?\n")
name = client_socket.recv(1024) # This might be a problem for someone with a reaaallly long name.
name = name.strip()
print "His name was Robert Paulson. Er, scratch that. It was {0}.".format(name)
client_socket.send("Thanks for calling, {0}. Bye, now.".format(name))
client_socket.close()
# Now, let's handle an actual connection:
while True:
client, addr = my_tcp_socket.accept()
print "Call from {0}:{1}".format(addr[0], addr[1])
client_handler = threading.Thread(target = handle_client,
args = (client,))
client_handler.start()
Unless you need the special sctp_ functions you don't need an sctp module at all.
Just use protocol 132 as IPPROTO_SCTP (is defined on my python3 socket module but not on my python2 socket module) and you can use the socket,bind,listen,connect,send,recv,sendto,recvfrom,close from the standard socket module.
I'm doing some SCTP C development and I used python to better understand SCTP behavior without the SCTP module.
Related
Ok guys, I can't understand this code:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
What does:
socket.AF_INET
socket.SOCK_STREAM
do?
I really read everything abount them, but I can't understand what dows they do, could you please explain me, them in simple words?Thanks for read, have a great day!
TL;DR
socket.AF_INET = The type of socket address
socket.SOCK_STREAM = The type of socket
Explanation
Whenever you provide socket.AF_INET to your server you instruct it to listen to an IPv4 address, and to your client to connect to an IPv4 address. This will work. Same for IPv6. However mixing them up doesn't.
That would be the same me waiting for you to talk to me on StackOverflow while you send me messages by email. We are not looking at the same spot, so we won't be able to communicate.
Same for socket.SOCK_STREAM (and the other values). The difference lies in the fact that this tells python's socket how we are going to communicate. socket.SOCK_STREAM will be TCP, while socket.SOCK_DGRAM will be UDP.
Let's come back to our "real world" example and let's imagine we agreed on communicating by email. I could expect either one email from you (explaining me everything you have to tell) or several (with a part of what you have to say in each email). That's the same as TCP vs UDP.
References
Well, I guess you have read both:
python's socket module
python's socket How to
Potentially:
SO: What is Address Family?
Wikipedia: IPv4
Also, I guess:
Difference Between Socket Types
(and the references therein)
Wikipedia: Network socket - Types
Super long explanation but mostly testing
So. If after all that you don't understand. Let's try:
# server.py
import socket
s = socket.socket()
s.bind(('localhost', 5050))
s.listen(5)
while True:
(clientsocket, address) = s.accept()
print 'client connected'
And:
# client.py
import socket
s = socket.socket(socket.AF_INET)
s.connect(('127.0.0.1', 5050))
print "Yeah! I'm connected :)"
So far, everything as in the how to.
We launch our server:
$ python server.py
And then we launch our client:
$ python client.py
Yeah! I'm connected :)
Everything works fine. That's good.
Now, lets change our client:
# client.py
import socket
s = socket.socket(socket.AF_INET6)
s.connect(('127.0.0.1', 5050))
print "Yeah! I'm connected :)"
And relaunch our new client:
$ python client.py
Traceback (most recent call last):
File "client.py", line 4, in <module>
s.connect(('127.0.0.1', 5050))
File "/.../lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 65] No route to host
Aie! Everything breaks!
But what happens? 127.0.0.1:5050 is an IPv4 address, hence the socket module tells us it's not happy about what we are doing! Indeed, we said our connection will be using an IPv6 address but we are providing it with an IPv4 address.
Okay... But if I use the same address but in IPv6, will it work? Let's try by changing our client (you could check out this SO answer for the equivalent of 127.0.0.1 for IPv6):
# client.py
import socket
s = socket.socket(socket.AF_INET6)
s.connect(('::1', 5050))
print "Yeah! I'm connected :)"
and our server:
# server.py
import socket
s = socket.socket(socket.AF_INET6)
s.bind(('::1', 5050))
s.listen(5)
while True:
(clientsocket, address) = s.accept()
print 'client connected'
We relaunch our server and our client:
$ python client.py
Yeah! I'm connected :)
Success!
The same procedure could be used to understand/test the socket.SOCK_STREAM parameter (but I think my answer is already long enough).
Hope this helped :).
socket.STREAM is the kind of socket you want. In this case, you are looking to stream bytes to and from the host you want to connect to, rather than just issue a one-time call. This means that the socket will listen for bytes until it receives an empty byte b'', at which point it will terminate the connection (because the stream is complete).
I would imagine you aren't too worried about the type of socket, so low-level understanding here isn't paramount, nor could I give you a particularly satisfactory answer to that, either.
socket.AF_INET is the AddressFamily, ipv4 or ipv6. This tells sockets what kind of address to expect. You will most likely use ipv4, so (host, port) tuple will work just fine.
AF_INET is well described in there. It is basically the method you are using for sending data over to the other socket. SOCK_STREAM basically describes that you are sending using TCP and essentially describes rules for the endpoint to which you are sending and recieving data (IP adress and port number).
But since you seem confused over these terms I'd suggest just just think of them as specifications on how you are going to transmit data between your two socket endpoints.
I'm using a relatively simple python execution, using OSC modules, in order to 'Send' code, from an application to an other.
import OSC
import threading
#------OSC Server-------------------------------------#
receive_address = '127.0.0.1', 9002
# OSC Server. there are three different types of server.
s = OSC.ThreadingOSCServer(receive_address)
# define a message-handler function for the server to call.
def printing_handler(addr, tags, stuff, source):
if addr=='/coordinates':
print "Test", stuff
s.addMsgHandler("/coordinates", printing_handler)
def main():
# Start OSCServer
print "Starting OSCServer"
st = threading.Thread(target=s.serve_forever)
st.start()
main()
Runned once, will work just fine, an listen on port 9002.
But, runned twice, will return ERROR:
socket.error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
My goal is to:
Be able to query on active thread's port
Close them
I've tried the following...
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = s.connect_ex(('127.0.0.1', 900socket2))
print 'RESULT: ', result
s.close()
But giving me unsuccessful result. (Returns 10061 both for active and unactive port's thread)
Python ยป Documentation socketserver.BaseServer:
shutdown()
Tell the serve_forever() loop to stop and wait until it does.
server_close()
Clean up the server. May be overridden.
What I would like to do is combine Twisted with the Cmd module in python's stdlib.
In short I would like to be able to get the bare-bones socket fd object from a connected Protocol to use as the stdin of the cmd.Cmd module in the stdlib.
In Long, My client that interfaces with my server uses the Cmd module to process commands and send those commands to the server.
On my server I would also like to use the same command processing method with the builting Cmd module. To do this i would need to specify the stdin and stdout of the command interpreter.
I could do this easily with the builtin sockets module, but i would like to do it with twisted if possible.
Here is some code to do what i want with plain sockets:
(Works with telnet)
# server
import socket
import cmd
class CmdProcessor(cmd.Cmd, object):
def __init__(self, sock, addr):
network = sock.makefile()
super(CmdProcessor, self).__init__(stdin=network, stdout=network)
self.sock = sock
self.addr = addr
# Run the cmd.Cmd processing loop
self.cmdloop()
def do_sayhi(self, args):
# When 'sayhi' is recieved over the socket,
self.sock.send("Hey yourself!")
def do_quit(self, args):
self.sock.close()
if __name__ == "__main__":
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sock.bind(("0.0.0.0", 2319))
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_sock.listen(5)
sock, addr = server_sock.accept()
print("Connection accepted")
connection = CmdProcessor(sock, addr)
This is almost what i want to to do. I just typed this up quick so i may be missing somthing. Half of it works. Currently, if you telnet into the server like:
telnet 127.0.0.1 2319
And you send 'sayhi' nothing happens. But if you type 'sayhi' at the terminal you started the server from (There is a (Cmd) prompt) the output goes to the telnet client. So the stdout of the cmd.Cmd is working. But not the stdin. That probably has something to do with the fact that telnet sends CR-LF ('\r\n') by default. Where the cmd module may just listen for \n.
So how can get the fd or file object from a protocol in twisted to do what i am trying do achieve here with bare sockets?
And any insights on what the input from telnet connected to the server is not registering with the CmdProcessor?
Any advice, tips or pointers welcome. (Wait no, no pointers.)
Thanks.
I suggest that instead you might want to look at Manhole.
In general, the point of Twisted is not to use Python socket objects directly. That's a big part of Twisted's job. When you want to interact with the network using Twisted, you use Twisted's APIs instead - protocols and transports, if you're thinking about the lowest level.
You can add use_rawinput = False
class CmdProcessor(cmd.Cmd, object):
use_rawinput = False
def __init__(self, sock, addr):
....
This produces response for sayhi from telnet
Dear all, I need to implement a TCP server in Python which receives some data from a client and then sends this data to another client. I've tried many different implementations but no way to make it run. Any help would be really appreciated.
Below is my code:
import SocketServer
import sys
import threading
buffer_size = 8182
ports = {'toserver': int(sys.argv[1]), 'fromserver': int(sys.argv[2])}
class ConnectionHandler(SocketServer.BaseRequestHandler):
def handle(self):
# I need to send the data received from the client connected to port 'toserver'
# to the client connected to port 'fromserver' - see variable 'ports' above
class TwoWayConnectionServer(threading.Thread):
def __init__(self):
self.to_server = SocketServer.ThreadingTCPServer(("", ports['toserver']), ConnectionHandler)
self.from_server = SocketServer.ThreadingTCPServer(("", ports['fromserver']), ConnectionHandler)
threading.Thread.__init__(self)
def run(self):
while (1):
self.to_server.handle_request()
self.from_server.handle_request()
def serve_non_blocking():
server = TwoWayConnectionServer()
server.run()
if __name__ == '__main__':
serve_non_blocking()
See the Twisted tutorial, and also twisted.protocols.portforward. I think that portforward module does something slightly different from what you want, it opens an outgoing connection to the destination port rather than waiting for the second client to connect, but you should be able to work from there.
Can you be more specific about what you tried and what didn't work? There are lots of ways to do this. Probably the easiest would be to use the socket library - maybe looking at some examples will help:
http://docs.python.org/library/socket.html#example
I'm currently writing a telnet server in Python. It's a content server. People would connect to the server via telnet, and be presented with text-only content.
My problem is that the server would obviously need to support more than one simultaneous connection. The current implementation I have now supports only one.
This is the basic, proof-of-concept server I began with (while the program has changed greatly over time, the basic telnet framework hasn't):
import socket, os
class Server:
def __init__(self):
self.host, self.port = 'localhost', 50000
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((self.host, self.port))
def send(self, msg):
if type(msg) == str: self.conn.send(msg + end)
elif type(msg) == list or tuple: self.conn.send('\n'.join(msg) + end)
def recv(self):
self.conn.recv(4096).strip()
def exit(self):
self.send('Disconnecting you...'); self.conn.close(); self.run()
# closing a connection, opening a new one
# main runtime
def run(self):
self.socket.listen(1)
self.conn, self.addr = self.socket.accept()
# there would be more activity here
# i.e.: sending things to the connection we just made
S = Server()
S.run()
Thanks for your help.
Implemented in twisted:
from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor
class SendContent(Protocol):
def connectionMade(self):
self.transport.write(self.factory.text)
self.transport.loseConnection()
class SendContentFactory(Factory):
protocol = SendContent
def __init__(self, text=None):
if text is None:
text = """Hello, how are you my friend? Feeling fine? Good!"""
self.text = text
reactor.listenTCP(50000, SendContentFactory())
reactor.run()
Testing:
$ telnet localhost 50000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello, how are you my friend? Feeling fine? Good!
Connection closed by foreign host.
Seriously, when it comes to asynchronous network, twisted is the way to go. It handles multiple connections in a single-thread single-process approach.
You need some form of asynchronous socket IO. Have a look at this explanation, which discusses the concept in low-level socket terms, and the related examples which are implemented in Python. That should point you in the right direction.
Late for the reply, but with the only answers being Twisted or threads (ouch), I wanted to add an answer for MiniBoa.
http://code.google.com/p/miniboa/
Twisted is great, but it's a rather large beast that may not be the best introduction to single-threaded asynchronous Telnet programming. MiniBoa is a lightweight, asynchronous single-threaded Python Telnet implementation originally designed for muds, which suits the OP's question perfectly.
For a really easy win implement you solution using SocketServer & the SocketServer.ThreadingMixIn
have a look a this echo server example it looks quite similar to what you're doing anyway: http://www.oreillynet.com/onlamp/blog/2007/12/pymotw_socketserver.html
If you're up for a bit of a conceptual challenge, I'd look into using twisted.
Your case should be trivial to implement as a part of twisted.
http://twistedmatrix.com/projects/core/documentation/howto/servers.html
If you want to do it in pure python (sans-twisted), you need to do some threading. If you havnt seen it before, check out:
http://heather.cs.ucdavis.edu/~matloff/Python/PyThreads.pdf
around page 5/6 is an example that is very relevant ;)
First, buy Comer's books on TCP/IP programming.
In those books, Comer will provide several alternative algorithms for servers. There are two standard approaches.
Thread-per-request.
Process-per-request.
You must pick one of these two and implement that.
In thread-per, each telnet session is a separate thread in your overall application.
In process-per, you fork each telnet session into a separate subprocess.
You'll find that process-per-request is much, much easier to handle in Python, and it generally makes more efficient use of your system.
Thread-per-request is fine for things that come and go quickly (like HTTP requests). Telnet has long-running sessions where the startup cost for a subprocess does not dominate performance.
Try MiniBoa server? It has exactly 0 dependencies, no twisted or other stuff needed. MiniBoa is a non-blocking async telnet server, single threaded, exactly what you need.
http://code.google.com/p/miniboa/
Use threading and then add the handler into a function. The thread will call every time a request i made:
Look at this
import socket # Import socket module
import pygame
import thread
import threading,sys
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port))
print ((host, port))
name = ""
users = []
def connection_handler (c, addr):
print "conn handle"
a = c.recv (1024)
if a == "c":
b = c.recv (1024)
if a == "o":
c.send (str(users))
a = c.recv (1024)
if a == "c":
b = c.recv (1024)
print a,b
s.listen(6) # Now wait for client connection.
while True:
c, addr = s.accept()
print 'Connect atempt from:', addr[0]
username = c.recv(1024)
print "2"
if username == "END_SERVER_RUBBISH101":
if addr[0] == "192.168.1.68":
break
users.append(username)
thread.start_new_thread (connection_handler, (c, addr)) #New thread for connection
print
s.close()