Python Server-Client Communication with each other - python

I am trying to modify a tcp/ip server-client communication. Only the server can communicate with the client. I am trying to find an easy a way to send a message back to the server. Not a chat !! Just a server which will send data to a client and receive data from the client.
I am using this example :
Server:
host="my_ip"
port=4446
from socket import *
s=socket()
s.bind((host,port))
s.listen(1)
print "Listening for connections.. "
q,addr=s.accept()
var = 1
while var == 1 :
data=raw_input("Enter data to be send: ")
q.send(data)
s.close()
Client:
host="my_ip"
port=4446
from socket import *
s=socket(AF_INET, SOCK_STREAM)
s.connect((host,port))
var = 1
while var == 1 :
msg=s.recv(1024)
print "Message from server : " + msg
#response = "Message delivered" # Response to be send
#s.sendto(response(host,port))
s.close()

Python actual has a built in class to make your life a bit easier. http://docs.python.org/2/library/socketserver.html. I'm not sure I understand the second part of your question however; you can simply send data back to the server in the same way you had the server send data to the client.

Use sock.sendall(). Also, you shouldn't just name a var "var" as it doesn't describe what it does. I would create a boolean instead and name it something like, "isListening" or "isSending".

Related

Python Socket, how do i choose between s.send and conn.send?

def send_Button():
try:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
except NameError:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
This program uses the tkinter module with socket in python2.7. My program allows for you to either connect to a server to chat with or host a server for others to connect to you, but whenever I try and test it out then the lines with the '###' on always bring up an error and it doesn't work, the error which comes up is: "NameError: global name 'conn' is not defined" OR "error: [Errno 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".
Any help please?
I think that you are trying to get the program to act as a Client or as a Server just changing s.send() to conn.send() saddly it isn't that simple.
Socket Initializzation
The socket have to be initialized before sending or receiving data.
For a client usually it's something like this.
send_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
send_socket.connect((serverIp, serverPort)) # Connect to the server
send_socket.send(data) # Send the data to the server
And like this for a Server:
listen_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
listen_socket.bind(("0.0.0.0", port)) # Set the socket to accept client from every interface on the port port
listen_socket.listen(1) # Put the server on listen on the port setted before
accept_socket, addr = self.listen_socket.accept() # when a client connect return the socket to talk with it
data = self.accept_socket.recv(buffer_size) # Receive data form the client of max size buffer_size
Docs examples
From your question I guess that with s.send() and conn.send() you are talking about
this example from the python 2.7 socket docs
Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client using it. Note that a server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect(). Also note that the server does not sendall()/recv() on the socket it is listening on but on the new socket returned by accept().
Client
Echo client program
import socket
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
the client is pretty stright forward, it create the socket s and then after using s.connect() it just send data through it.
Server
The server one is where there there are both s and conn
Echo server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
conn.close()
in this one first of all we create a socket s on which the server will listen and then using s.accept() it will wait till a client connect to the server and then return the conn which is the socket of the connected client.
So to receive or send data to the client you have to use conn.
Notes
As said in the documentation in these two example the server accept only one client. So if you want to deal with multiple clients you have to repeat the accept step and possibly generate a new Thread for each client so that other clients don't have to wait for each others.

Python efficient socket communication

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.

s.sendall doesn't work inside a thread in python

I'm trying to develop a chat program in python. I want it to have multiple clients so I'm using threading to handle this. However when I try to send the message to all connected clients, the server only sends it to the client which sent the message. I'm not sure if I'm just missing something obvious but here is the code for the server:
import socket
from thread import *
host = '192.168.0.13'
port = 1024
users = int(input("enter number of users: "))
def clienthandler(conn):
while True:
data = conn.recv(1024)
if not data:
break
print data
conn.sendall(data)
conn.close()
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.bind((host, port))
serversock.listen(users)
for i in range(users):
conn, addr= serversock.accept()
print 'Connected by', addr
start_new_thread(clienthandler, (conn,))
And here is the code for the client:
import socket
host = '192.168.0.13'
port = 1024
usrname = raw_input("enter a username: ")
usrname = usrname + ": "
clientsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsock.connect((host, port))
while True:
x = raw_input('You: ')
x = usrname + x
clientsock.sendall(x)
data = clientsock.recv(1024)
print data
The "all" in sendall means that it sends all of the data you asked it to send. It doesn't mean it sends it on more than one connection. Such an interface would be totally impractical. For example, what would happen if another thread was in the middle of sending something else on one of the connections? What would happen if one of the connections had a full queue?
sendall: Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent. -- 17.2. socket
You can try by pulling up the list of users, and iterating through it, and doing an individual send of the same message, though, unless you are the administrator and want to broadcast a warning, this functionality would be pretty mundane.

Communicating with multiple clients using one TCP socket python

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.

chat between server and a client in different computers connected to the same wifi using python sockets

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

Categories