I have just started learning python and i was wondering how i would get the client to execute a function on the server and get some response
Here is my server code
import socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 8089))
serversocket.listen(5)
while True:
connection, address = serversocket.accept()
buf = connection.recv(64)
if len(buf)> 0:
print(buf)
break
input('press enter')
This is the client code
import socket
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 8089))
data = 'lorem ipsum'
clientsocket.send(data.encode())
input('press enter')
and this is the function
def addme(x,y):
return x + y
print (addme(6,4))
Supposing i have the function addme() on the server,would it be possible to call it from the client and the response displayed to the client?.
If you simply want to call functions you should check out XMLRPC. Simple and easy, here's the example from the python documentation.
# Server code
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
def is_even(n):
return n%2 == 0
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(is_even, "is_even")
server.serve_forever()
# Client code
import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
print "3 is even: %s" % str(proxy.is_even(3))
print "100 is even: %s" % str(proxy.is_even(100))
You'd have to send it some sort of message telling the server to execute this. For example you could send it a string "ADDME", when the server receives this, it stores addme()'s result and sends it back to the client which then prints it.
You need to set up your own communication protocol. Invent a command that, when you send it, makes the server execute some function.
To send data over a socket (comparable to a file-like object) you need to serialize (encode) it into a set of bytes, and, after receiving these bytes on the other end, deserialize (decode) those.
Encode the function's return value to e.g. JSON in case it is dictionary, to str in case it is an integer, or invent your own binary protocol or, if you would like to be able to send almost any kind of Python object through "the wire", then pickle the return value. Send the encoded (pickled) return value to the client. It has to decode (unpickle) it then.
In any case, you will have to implement your own protocol, with its own set of commands, while each command might have arguments. You will have to find a way to separate the command from its argument and will have to (in)validate commands you receive.
For learning network communication, your task is great. For implementing a production software, you must have a look and rock-solid messaging libraries such as xmlrpclib as pointed out by others.
Sounds like you are trying to implement RPC. See here for a discussion on existing libraries: What is the current choice for doing RPC in Python?
This is how i did it
server.py
from xmlrpc.server import SimpleXMLRPCServer
def addme(x,y):
return x + y
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(addme, "addme")
server.serve_forever()
input('press enter')
client.py
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
print("the sum: %s" % str(proxy.addme(6,4)))
input('press enter')
Related
I am experimenting with python sockets to try to understand the whole concept better, but I have run into a problem. I have a simple server and a client, where the client sends a list to the server, and then waits for the server to send a string signaling the process is complete.
This is the client file:
import socket
import json
host = '192.168.1.102'
port = 14314
def request():
print 'Connecting'
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect((host, port))
print 'Sending request'
clientsocket.sendall(json.dumps([1, 2, 3, 4, 5, 6, 7, 8, 9]))
print 'Receiving data'
data = clientsocket.recv(512)
print 'Received: {}'.format(data)
request()
and here is the server file:
import socket
import json
host = '192.168.1.102'
port = 14314
def run():
print 'Binding socket'
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind((host, port))
print 'Waiting for client'
serversocket.listen(1)
clientsocket, addr = serversocket.accept()
print 'Receiving data'
raw_data = ''
while True:
tmp = clientsocket.recv(1024)
if not tmp:
break
raw_data += tmp
data = json.loads(raw_data)
print 'Received: {}'.format(data)
print 'Sending data'
clientsocket.sendall('done')
run()
The problem is that while the client is done sending the list, the server is stuck in the recv loop, waiting for nothing. The whole data has been received in the first iteration and in the second iteration there is nothing to be received because the client has moved on to the receiving part.
The weird part is that if I comment out the receive part from the client and the send part from the server, the process completes successfully. So, what am I doing wrong? Why is this not working?
Thanks.
The Docs for socket.recv talk about additional flags being able to be passed in to the recv function described in the unix documentation. So turning to that documentation, I found the following message:
If no messages are available at the socket, the receive calls wait for
a message to arrive, unless the socket is nonblocking (see fcntl(2)),
in which case the value -1 is returned
So once again, we're directed to another page. The documentation for fcntl says
Performs one of the operations described below on the open file
descriptor
So, normally the socket.recv function is blocking (it will wait indefinitely for new data), unless we use a file descriptor. How do we do that? Well there is a socket.makefile function that gives us a file descriptor attached to the socket. Cool. This SO question gives us an example of how we can read and write to a socket, using a file descriptor.
Well what if we don't want to use a file descriptor. Reading further into the unix documentation for the recv function, I see that I can use the MSG_DONTWAIT flag. This doesn't work in Windows, but I did find out that we can use socket.setbocking(False) to permamently change the socket to non-blocking mode. You would then need to ignore any "A non-blocking socket operation could not be completed immediately" errors. Those are normal and non-fatal(error #10035 of this page mentions it is non-fatal).
Another possible implementation would be to multi-thread your program, you can implement a receiving and a sending thread for your socket. This might give you the best performance, but it would be a lot of work to setup.
Python is awesome. I just found some libraries Python has that does asynchronous sockets too. There's asyncore, asynchat which have both been deprecated in favor of asyncio if that is available in the version of Python you are using.
Sorry for throwing so much out there. I don't know a whole lot about sockets. I used them once with the Paramiko library, and that was it. But it looks like there are a lot of ways of implementing them.
Write down the chatting program code base with SSL/TLS and MultiThreading.
there's a 3 things to follow.
1.when client connected client's ID and IP or Network interface information, network information.
2.when client send message you have to follow this form([Client ID#connect IP] Message ) everytime.
3.you have to show and explain flowchart with client and server program.
it's my final exam of network programing. but it's too hard for me. i couldn't write down the code. so i have to submit the paper with nothing. i don't know how to do. someone can explain how to code the program?
my code is
server.py
import socket
import thread
print '---python chatting program---'
host = ''
port = 27332
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
users = []
def service(conn):
try:
name = conn.recv(1024)
str = '*' + name + ' is entered.*'
while conn:
print str
for each in users:
each.send(str)
str = name + ' : ' + conn.recv(1024)
except:
users.remove(conn)
str = '*' + name + ' is out.*'
print str
if users:
for each in users: each.send(str)
# thread.start_new_thread(service, ())
while 1:
conn, addr = s.accept()
global users
users.append(conn)
thread.start_new_thread(service, (conn, ))
pass
client.py
import socket
import thread
def handle(socket):
while 1:
data = socket.recv(1024)
if not data:
continue
print data
print 'handler is end.'
host = '127.0.0.1'
port = 27332
print 'enter your name.'
name = raw_input()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(name)
thread.start_new_thread(handle, (s, ))
while 1:
msg = raw_input()
if not msg:
continue
s.send(msg)
s.close()
print '---chatting program is end---'
The official Python documentation provides an example of how to use Python's native socket package to implement a simple echo server and client. The example itself contains essentially no real functionality (since the goal here is to demo the use of socket): the server echoes back everything it receives from the client. However, you can use this code as a basis, adding the functionality as required. If you use Python 3, you'll find the documentation here, for Python 2 see here.
Now for the SSL/TLS part. Python has a native module ssl which is a TLS/SSL wrapper for socket objects; to cite the official Python documentation: the module "provides access to Transport Layer Security (often known as “Secure Sockets Layer”) encryption and peer authentication facilities for network sockets". If you use Python 3, you can find the documentation for the ssl module here, for Python 2 see here.
The ssl module provides the class ssl.SSLSocket, which is derived from the socket.socket type, and provides a socket-like wrapper that also encrypts and decrypts the data going over the socket with SSL. The official documentation also contains example code (snippets) you can use to implement your exercise (see e.g. here for how to do SSL/TLS using ssl module in Python 3).
i recently started making a pure skype resolver and after doing everything fine i stuck on the socket communication.
Let me explain
I'm using python to get the user's IP and then the script opens a socket server and it sends the username to an other program written in .NET
Why is that? Well, the python skype API is not that powerfull so i'm using the axSkype library in order to gather more info.
The problem
The python socket sends the username as it should but i dont know the most efficient way to get the info back. I was thinking opening a socket server in the same script and wait for what the .NET program sends back.
I dont really kwon how to make this as fast as possible so i'm asking for your help.
The code
class api:
def GET(self, username):
skypeapi.activateSkype(username)
time.sleep(1) # because skype is ew
buf = []
print("==========================")
print("Resolving user " + username)
#This is where i'm starting the socket and sending data
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 5756))
s.sendall(username)
s.close()
#at this poaint i want to get data back from the .NET app
for logfile in glob.glob('*.log'):
buf += logparse.search(logfile, username)
print("Done!")
print("==========================")
return json.dumps(buf)
class index:
def GET(self):
return render.index()
if __name__ == "__main__":
app.run()
You can bind your socket to the connection. This way, your socket stream will remain open and you will be able to send and receive information easily. Integrate this with the _thread module and you will be able to handle multiple streams. Here is some example code that binds a socket to a stream and just sends back whatever the clients sends it(Although in your case you could send whatever data is necessary)
import socket
from _thread import *
#clientHandle function will just receive and send stuff back to a specific client.
def clientHandle(stream):
stream.send(str.encode("Enter some stuff: "))
while True:
#Here is where the program waits for a response. The 4000 is a buffer limit.
data = stream.recv(4000)
if not data:
#If there is not data, exit the loop.
break
stream.senddall(str.encode(data + "\n"))
#Creating socket.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "" #In this case the host is the localhost but you can put your host
port = 80
try:
#Here the program tries to bind the socket to the stream.
s.bind((host, port))
except socket.error as e:
print("There was an error: " + str(e))
#Main program loop. Uses multithreading to handle multiple clients.
while True:
conn, addr = s.accept()
print("Connected to: " + addr[0] + ": " + str(addr[1]))
start_new_thread(clientHandle,(conn,))
Now in your case, you can integrate this into your api class(Is that where you want to integrate it? Correct me if I'm wrong.). So now when you define and bind your socket, use this code:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
Where, in your case, host is 127.0.0.1, in other words, your localhost, which can also be accessed by socket.gethostbyname(socket.gethostname())(but that's a bit verbose), and then port, which for you is 5756. Once you have bounded your socket, you have to accept connections through the following syntax:
conn, addr = s.accept()
Which then you can pass conn and addr to whatever function or just use in any other code.
Regardless of what you use it in, to receive data you can use socket.recv() and pass it a buffer limit. (Remember to decode whatever you receive.) And of course, you send data by using socket.sendall().
If you combine this with the _thread module, as shown above, you can handle multiple api requests, which could come handy in the future.
Hope this helps.
I am using TCP sockets to communicate between my server and clients. The server code and socket code are as below:
server:
from socket import *
HOST = 'xx.xx.xx.xx'
PORT = 1999
serversocket = socket(AF_INET,SOCK_STREAM)
serversocket.bind((HOST,PORT))
print 'bind success'
serversocket.listen(5)
print 'listening'
while True:
(clientsocket, address) = serversocket.accept()
print ("Got client request from",address)
#clientsocket.send('True')
data = clientsocket.recv(1024)
print data
clientsocket.send('True')
clientsocket.close()
client:
import socket
import sys
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port on the server given by the caller
server_address = ('xx.xx.xx.xx', 1999)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)
try:
message = 'This is the message. It will be repeated.'
print >>sys.stderr, 'sending'
for x in range (0,1):
name=raw_input ('what is ur name')
print type(name)
sock.send(name)
print sock.recv(1024)
finally:
sock.close()
I am able to communicate with the server from client and able to send and receive data. But the problem I am facing is that I am not able to send and receive data continuously from the server. I have to restart my client code on my laptop to send and receive data again from the server. The way the above client code is working is that when I give a keyboard input, then the socket sends data to server and server responds back. But in the client code, in the for loop if I do two iterations, for the second iteration the data I enter from keyboard is not reaching server. I need to restart my client code to send data again. How do I fix this ?
Also, when once client is connected to the server, the other cannot connect to the server. Any ideas on how to do this ?
You need to design and implement a protocol that specifies what each side is supposed to do and then implement that protocol. You're expecting it to work by magic.
For example:
data = clientsocket.recv(1024)
I suspect you are expecting this to receive a "message". But TCP has no notion of messages. If you need to send and receive messages, you need to define precisely what a "message" is for your protocol and write code to send and receive them.
It may be helpful to look at the specifications for other protocols that use TCP such as HTTP, FTP, or IRC. It really is worth the time to write out a specification of your protocol before you write any code. It will save a lot of pain.
iam facing some problems as i was working to extend a simple chat program over the wifi.
Ive named the two programs running on different systems as client and server thought they don't perform their typical functions.
the message sent by the client is correctly displayed by the server program but once the server sends the message it is not received by the client program.Ive checked the IP and everything is fine. both the client and server codes are also similar the only difference is in who sends the message first(client according to my program) .
I need help with this as soon as possible.
thanks in advance.
this is my client program
from socket import *
import sys
import time
TO_ADDR=('192.168.1.101',8135)
hostname=gethostbyname('0.0.0.0')
LOCAL_ADDR=(hostname,8138)
MSG_LEN=1000
fd=socket(AF_INET, SOCK_DGRAM)
fd.bind(LOCAL_ADDR)
s=('',)
msg=''
def recv():
s=fd.recvfrom(MSG_LEN)
print '\n',s[0]
print '\n'
return s[0]
def send(msg):
fd.connect(('192.168.1.101',8135))
fd.sendto(msg,TO_ADDR)
while msg!='stop' or s!='stop':
print '\n'
msg=raw_input('Enter your message:')
send(msg)
s=recv()
print '\n',s[0]
this is my server program
from socket import *
s=('',)
msg=''
TO_ADDR=('198.168.1.103',8138)
hostname=gethostbyname('0.0.0.0')
LOCAL_ADDR=(hostname,8135)
MSG_LEN=1000
fd=socket(AF_INET,SOCK_DGRAM)
fd.bind(LOCAL_ADDR)
def recv():
s=fd.recvfrom(MSG_LEN)
print '\n',s[0]
print '\n'
return s[0]
def send(msg):
fd.connect(('198.168.1.103',8138))
fd.sendto(msg,TO_ADDR)
fd.close()
while s[0]!='stop' or msg!='stop':
s=recv()
msg=raw_input('Enter your message:')
send(msg)
UDP (you are using SOCK_DGRAM) is a stateless protocol. You cannot therefore "connect" to the client from the server as you are trying to do in your code.
See: UDP Communication
You have to do something like this:
data, addr = fd.recvfrom(1024)
fd.sendto(data, addr)
You could change your recv() function to:
def recv():
data, addr = fd.recvfrom(MSG_LEN)
print '\n',s[0]
print '\n'
return data, addr
And your send() function to:
def send(msg, addr):
fd.sendto(msg, addr)
And the last part of your code to:
while s[0]!='stop' or msg!='stop':
data, addr = recv()
msg = raw_input('Enter your message:')
send(msg, addr)
See:
socket.recvfrom
socket.sendto