Two-way communication using AF_UNIX socket - python

I'd like to implement the example from python official documentation on socket module using AF_UNIX socket instead of AF_INET. So here's how server code looks now:
import socket
import os
filename = '/tmp/mysock'
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
if os.path.exists(filename):
os.remove(filename)
sock.bind(filename)
while 1:
data = sock.recv(1024)
print 'Received', repr(data)
if not data:
break
sock.sendall(data)
sock.close()
When I run it, I get this:
Traceback (most recent call last):
File "/home/somecode/server.py", line 10, in <module>
data = sock.recv(2048)
socket.error: [Errno 22] Invalid argument

SOCK_STREAM is a stateful socket type, so any connection must first be acknowledged by a listening socket and then new dynamic socket (connection) is used for sending and receiving instead. You can't just receive from listening socket.
Basically you forgot to call sock.listen() on socket after binding and connection, address = sock.accept(), which blocks until a connection is established and then returns tuple with new socket (connection) and client address. Then simply use connection.recv(). This is universal for UNIX sockets and TCP/IP sockets.
For example have a look here.

Related

Python socket.send not working

Simple client - server app.
#Server use decode
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host,port))
s.listen(5)
while True:
c,addr = s.accept()
print("Got connection from " + str(addr))
ret_val = s.send("Thank you".encode('utf-8'))
print ("ret_val={}".format(ret_val))
c.close()
Client:
#client use decode
from socket import gethostname, socket
serSocket = socket()
server = gethostname()
port = 12345
serSocket.connect((server, port))
data = serSocket.recv(1024)
msg = data.decode('utf-8')
print("Returned Msg from server: <{}>".format(msg))
serSocket.close()
when the server tries to send the following exception occurred
Traceback (most recent call last):
Got connection from ('192.168.177.1', 49755)
File "C:/Users/Oren/PycharmProjects/CientServer/ServerSide/Server2.py", line 16, in <module>
ret_val = s.send("Thank you".encode('utf-8'))
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
Process finished with exit code 1
As can be seen the client connects the server successfully.
But send fails.
What is the problem?
The problem is that you are sending on the listening socket, not on the connected socket. connect returns a new socket which is the one you must use for data transfer. The listening socket can never be used for sending or receiving data.
Change the send to this and your program will work fine:
ret_val = c.send("Thank you".encode('utf-8'))
(Note c.send, not s.send)

"[Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted" after closing and reopening Python socket

I have this code:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind(('10.0.0.253', 8080))
except:
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('10.0.0.253', 8080))
s.listen(1)
conn, addr = s.accept()
which binds, then if it encounters an error with that, destroys the socket then creates a new one and binds it to the same IP and port. For some reason, even after closing the socket, I get this error:
Traceback (most recent call last):
File "C:\Users\other\Desktop\tcpReverseShell_Server.py", line 68, in <module>
main()
File "C:\Users\other\Desktop\tcpReverseShell_Server.py", line 66, in main
connect()
File "C:\Users\other\Desktop\tcpReverseShell_Server.py", line 43, in connect
s.bind(('10.0.0.253', 8080))
File "C:\Python27\lib\socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
error: [Errno 10048] Only one usage of each socket address (protocol/network
address/port) is normally permitted
The only solution I've found is to use s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1), but when I try that I get this error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions. I
I am on Windows 10, Python 2.7.13.
I can simulate your problem by running the python script twice concurrently. The problem is that some other application is currently also using the socket.
In your code, the except block is triggered when your socket fails to bind. However, when you try to .close() the socket and try again, it does nothing as it is trying to .close() an unbound socket. Hence, your code is equivalent to:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('10.0.0.253', 8080))
s.listen(1)
conn, addr = s.accept()
Note that when you .close() the socket, it also does not .close() the currently bound application, it attempts to .close() to socket object you created. So, trying to bind the socket again will fail.
To find out what is using the socket, you can use netstat:
netstat -aon | findstr :8080
This should give you something like:
TCP 127.0.0.1:8080 0.0.0.0:0 LISTENING 6604
Then, if you want to kill it forcefully, you can use TaskKill and the application's PID:
TaskKill /PID 6604 /F

Why python raises exception on udp recvfrom

I have realy simple python27 script on Windows10
It is just sends messages and waits for reply using udp socket
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = "Hello, World!"
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
print "message:", MESSAGE
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
sock.recvfrom(1200)
On Windows 10 it raises exception
Traceback (most recent call last):
File "simple.py", line 14, in <module>
print sock.recv(1200)
socket.error: [Errno 10054]
On Linux it works fine.
What i am doing wrong ?
The first several lines of your program are opening a socket to send data which all is fine. But the sock.recvfrom line doesn't have an associated bind with it.
In other words, when you send on UDP you shouldn't expect to receive anything back. If you want to send a message and then wait for a reply (which will not be automatic from a remote system) you need to bind the socket to a listening port.
This site: https://wiki.python.org/moin/UdpCommunication has some great references.
I found solution here Windows UDP sockets: recvfrom() fails with error 10054 Author made the same. He ignores this error. But maybe it is true way of solving this problem.
I just put recvfrom in while and wrapped it with try..except
And I ignore any errors. It worked for me

Python server-client

I need some help. I have a simple server:
host="localhost"
port=4447
from socket import *
import thread
def func():
while 1:
data = conn.recv(1024)
if not data:
continue
else:
print("%s said: %s")%(player, data)
conn.close()
s=socket(AF_INET, SOCK_STREAM)
s.bind((host,port))
s.listen(2)
print("Waiting for clients on localhost, port %s")%port
while 1:
conn, addr = s.accept()
player = addr[1]
print(conn)
thread.start_new_thread(func,())
And a simple client:
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 4447
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
while 1:
data = raw_input("Input: ")
s.send(data)
So when I connect to the server I can type anything and it is printed in the server's terminal. When I open another terminal and start second client I can also type anything and it is sent to the server, but when I go back to the first client's terminal and type several messages, it returns:
Traceback (most recent call last):
File "Client.py", line 18, in <module>
s.send(data)
socket.error: [Errno 32] Broken pipe
So I fixed that with adding conn as a parameter in func(), but I don't understand why this error happened? Could anyone please explain it to me?
Thanks!
Your func, apart from needing a better name, uses global state in your program to communicate with a client. No matter how many threads you start to handle client connections, there's still only one global conn variable. Each time a new client connects, your main thread loop rebinds conn to the new connection. The old socket is thrown away and automatically closed by the Python runtime.
You can fix this by removing the use of global variables to track per-connection state. A better route to explore, though, is Twisted.

Python ssl problem with multiprocessing

I want to send data from a client to the server in a TLS TCP socket from multiple client subprocesses so I share the same ssl socket with all subprocesses. Communication works with one subprocess, but if I use more than one subprocesses, the TLS server crashes with an ssl.SSLError (SSL3_GET_RECORD:decryption failed or bad record mac).
More specific: It does not depend which process first calls the SSLSocket.write() method, but this process is the only one from this time on which can call it. If another process calls write(), the server will result in the exception described above.
I used this basic code:
tlsserver.py
import socket, ssl
def deal_with_client(connstream):
data = connstream.read()
while data:
print data
data = connstream.read()
connstream.close()
bindsocket = socket.socket()
bindsocket.bind(('127.0.0.1', 9998))
bindsocket.listen(5)
while True:
newsocket, fromaddr = bindsocket.accept()
connstream = ssl.wrap_socket(newsocket,
server_side=True,
certfile="srv.crt",
keyfile="srv.key",
ssl_version=ssl.PROTOCOL_TLSv1)
deal_with_client(connstream)
tlsclient.py
import socket, ssl
import multiprocessing
class SubProc:
def __init__(self, sock):
self.sock = sock
def do(self):
self.sock.write("Test")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s)
ssl_sock.connect(('127.0.0.1', 9998))
print "Connected to", repr(ssl_sock.getpeername())
for x in (1,2):
subproc = SubProc(ssl_sock)
proc = multiprocessing.Process(target=subproc.do)
And this is the backtrace:
Traceback (most recent call last):
File "tlsserver.py", line 21, in <module>
deal_with_client(connstream)
File "tlsserver.py", line 7, in deal_with_client
data = connstream.read()
File "/usr/lib64/python2.6/ssl.py", line 136, in read
return self._sslobj.read(len)
ssl.SSLError: [Errno 1] _ssl.c:1325: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac
The problem is that you're re-using the same connection for both processes. The way SSL encrypts data makes this fail -- the two processes would have to communicate with each other about the state of the shared SSL connection. Even if you do make it work, or if you didn't use SSL, the data would arrive at the server all jumbled up; you would have no real way of distinguishing which bytes came from which process.
What you need to do is give each process its own SSL connection, by making the connection in subproc.do. Alternatively, don't have the subprocesses communicate with the server at all, but rather communicate with the main process, and have the main process relay it over the SSL connection.

Categories

Resources