I'm sorry if this is a really dumb question, I'm sure someone could probably find the answer in a minute, I've just recently been getting into Python sockets.
I want my server to continually send a stream of data to my client, but for some reason, after receiving the first piece of data my client just does not receive/print out any more data.
My simplified server.py:
while True:
#do some stuff with dfwebsites here
senddata = True
#time.sleep(1)
#Starting the sending data part
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1236))
s.listen(5) #queue of five
while senddata==True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
d = pd.DataFrame(dfwebsites)
msg = pickle.dumps(d)
#header to specify length
#msg = "Welcome to the server!"
msg = bytes(f'{len(msg):<{HEADERSIZE}}','utf-8')+msg
clientsocket.send(msg) #type of bytes is utf-8
#clientsocket.close()
senddata = False
My client.py:
import socket
import pickle
import time
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1236))
while True:
full_msg = b''
new_msg = True
while True:
msg = s.recv(1024)
if new_msg:
print("new msg len:",msg[:HEADERSIZE])
msglen = int(msg[:HEADERSIZE])
new_msg = False
print(f"full message length: {msglen}")
full_msg += msg
print(len(full_msg))
if len(full_msg)-HEADERSIZE == msglen:
print("full msg recvd")
print(full_msg[HEADERSIZE:])
print(pickle.loads(full_msg[HEADERSIZE:]))
new_msg = True
full_msg = b""
Why can it not receive more than one peice of data?
Thank you so much for your help! I would really love even a comment telling me how to improve my qeustion!
To send more than one message to each client, you need a loop after the accept() has happened.
#!/usr/bin/env python
import socket
import pickle
import pandas as pd
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1236))
s.listen(5) # only one client at a time, but let up to five wait in line
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
while senddata:
# FIXME: refresh dfwebsites every time through this loop?
d = pd.DataFrame(dfwebsites)
msg = pickle.dumps(d)
msg = bytes(f'{len(msg):<{HEADERSIZE}}','utf-8')+msg
try:
clientsocket.send(msg) #type of bytes is utf-8
except socket.error as exc:
print(f"Ending connection from client {address} due to {exc}")
# FIXME: Do the below only when you want to disconnect a client
#senddata = False
clientsocket.close()
Related
I was writing an echo server but recv() does not return while the sender process is alive. If I use one recv() call instead of my recvall() function, it is returning and working. Please let me know what is wrong with recvall() function..
Server:
import socket
def recvall(skt):
msg_total = b""
while True:
msg = skt.recv(1024)
if not msg: break
msg_total += msg
return msg_total
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost",3333))
s.listen()
conn,addr = s.accept()
# data = conn.recv(1024) <= this recv() is not blocking
data = recvall(conn)
conn.sendall(data)
main()
Client:
import socket
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost",3333))
msg = ("a" * 10).encode()
s.sendall(msg)
rsp = s.recv(1024)
main()
I have a client and a server in python, my server is consistently sending the time to my client. My client then prints the time received, the length of the message, and that the full message was received. I know how to incorporate a basic GUI, but when I do the flow of data stops exactly where the GUI was placed. I need the GUI to display the time as it receives it, constantly updating.
This is my first python project so I'm sure I'm missing something.
I'm honestly unsure of how to go about this. Any ideas are helpful.
This Is my server
import socket
import time
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1243))
s.listen(5)
while True:
# now our endpoint knows about the OTHER endpoint.
clientsocket, address = s.accept()
print(f"Connection from {address} has been established.")
msg = "Welcome to the server!"
msg = f"{len(msg):<{HEADERSIZE}}"+msg
clientsocket.send(bytes(msg,"utf-8"))
while True:
time.sleep(3)
msg = f"The time is {time.time()}"
msg = f"{len(msg):<{HEADERSIZE}}"+msg
print(msg)
clientsocket.send(bytes(msg,"utf-8"))
This is my client
import socket
HEADERSIZE = 10
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1243))
while True:
full_msg = ''
new_msg = True
while True:
msg = s.recv(60)
if new_msg:
print("new msg len:",msg[:HEADERSIZE])
msglen = int(msg[:HEADERSIZE])
new_msg = False
print(f"full message length: {msglen}")
full_msg += msg.decode("utf-8")
print(len(full_msg))
if len(full_msg)-HEADERSIZE == msglen:
print("full msg recvd")
print(full_msg[HEADERSIZE:])
new_msg = True
full_msg = ''
This is what the server results:
Connection from ('169.254.91.3', 64486) has been established.
29 The time is 1563997982.918763
30 The time is 1563997985.9197025
0 The time is 1563997988.9197063
This is what the client results:
new msg len: b'22
'
full message length: 22
32
full msg recvd
Welcome to the server!
new msg len: b'29
'
full message length: 29
39
full msg recvd
The time is 1563997982.918763
new msg len: b'30
'
full message length: 30
40
full msg recvd
The time is 1563997985.9197025
new msg len: b'30
'
full message length: 30
40
full msg recvd
The time is 1563997988.9197063
You can create a Text box to capture the messages received. In order to not blocking the GUI mainloop, you need to use thread to handle server connection. Below is an example:
import socket
import threading
from tkinter import *
HEADERSIZE = 10
# function to handle server connection
def connect_server(logbox):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1243))
while True:
msg = s.recv(60).decode()
print(msg)
msglen = int(msg[:HEADERSIZE])
if len(msg) == msglen+HEADERSIZE:
logbox.insert(END, f'{msg[HEADERSIZE:]}\n')
else:
logbox.insert(END, 'Received invalid message\n')
logbox.see(END)
# create the GUI
root = Tk()
logbox = Text(root, width=60, height=10)
logbox.pack(fill=BOTH, expand=1)
# start the server handling thread
threading.Thread(target=lambda:connect_server(logbox), daemon=True).start()
# start the GUI mainloop
root.mainloop()
my raspberry pi is the server and Im trying to send continuous message from rpi to android while recieving a command from client (android app),i really dont know if this is possible and how to do it is out of my reach and it is not a feedback message here is my code hope you will help me thank you.
import apptopi
from socket import *
from time import ctime
from nanpy import (ArduinoApi, SerialManager)
apptopi.setup()
connection = SerialManager()
a = ArduinoApi(connection = connection)
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
add = 0
add += 1
a = str(add) //**this is a sample that i want to send continously
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(0)
tcpSerSock.send(str.encode(a)) <== i really don't know how to send
continuously
while True:
print 'Waiting for connection'
tcpCliSock,addr = tcpSerSock.accept()
print '...connected from :', addr
try:
while True:
data = ''
data = tcpCliSock.recv(BUFSIZE)
if not data:
break
if data == ctrCmd[0]:
apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
apptopi.back()
print 'backward'
if data == ctrCmd[2]:
apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
apptopi.stp()
print 'stop'
except KeyboardInterrupt:
apptopi.close()
GPIO.cleanup()
tcpSerSock.close();
OK one approach is to use the select() function for this. There is information in the documentation about its operation.
As an example I've made a modified version of your program (see below). I don't have a raspberry pi, so that part of the code is commented out, but you can replace it as needed.
The example uses the timeout feature of select() to send "continuous" messages to clients whilst also monitoring them for incoming messages. You can adjust the message contents and timeout to whatever works for you. NB you may also need to respond to client messages, as this code only sends data to clients after a timeout. Make whatever changes you need.
import sys
import socket
import select
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(1)
print 'Waiting for connection'
sendInterval = 1.0 # interval(sec) for sending messages to connected clients
rxset = [tcpSerSock]
txset = []
while 1:
rxfds, txfds, exfds = select.select(rxset, txset, rxset, sendInterval)
if rxfds:
for sock in rxfds:
if sock is tcpSerSock:
# a client is connecting
tcpCliSock, addr = tcpSerSock.accept()
tcpCliSock.setblocking(0)
rxset.append(tcpCliSock)
print '...connected from :', addr
else:
# a client socket has data or has closed the connection
try:
data = sock.recv(BUFSIZE)
if not data:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
if data == ctrCmd[0]:
#apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
#apptopi.back()
print 'backward'
if data == ctrCmd[2]:
#apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
#apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
#apptopi.stp()
print 'stop'
except:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
# timeout - send data to any active client
for sock in rxset:
if sock is not tcpSerSock:
sock.send("Hello!\n")
The simple client program I used to test this is here:
import sys
import socket
import time
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = '127.0.0.1'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpCliSock.connect(ADDR)
time.sleep(1)
for i in range(len(ctrCmd)):
tcpCliSock.send(ctrCmd[i])
time.sleep(1)
data = tcpCliSock.recv(BUFSIZE)
print data
tcpCliSock.close()
Hope this helps, best of luck.
In socket, I found that if server does not send any message before call recv(), server will be no response, whatever using mutilthread or not.
As the figure shows below:
enter image description here
enter image description here
server.py(Using SocketServer module):
def handle(self):
conn = self.request
# conn.send('Welcome to server')
flag = True
while flag:
data = conn.recv(1024)
print 'client:' + data
if data == 'exit':
flag = False
conn.send('AAAAAA')
conn.close()
client.py:
client = socket.socket()
ip_port = ('127.0.0.1', 11111)
client.connect(ip_port)
while True:
data = client.recv(1024)
print 'server:' + data
send = raw_input('client:')
client.send(send)
if send == 'exit':
sys.exit()
I would appreciate it very much if you would help me with it.
# server.py
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "Server received data:", data
conn.send("Data received at server side")
conn.close()
# client.py
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
print "Client: " + MESSAGE
data = s.recv(BUFFER_SIZE)
s.close()
print data
I think providing a sample code could speak itself.
# Expected input:
python server.py
python client.py
# Expected output:
# (server output)
Connection address: ('127.0.0.1', 62136)
Server received data: Hello World!
# (client output)
Client: Hello World!
Data received at server side
You could find out your missing component by comparing the code,such as bind().
Hope it help.
With reference to this site: https://wiki.python.org/moin/TcpCommunication
I have made a chat program (in this moment only host can send messages):
server:
# server
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = 150
server.bind((host, port))
print 'Server is open\nWaiting connections...'
server.listen(1)
while True:
client, addr = server.accept()
print 'Connected by', addr
while True:
HERE IS THE PROBLEM:when i type messages and i send they , the client see only messages with a even number. why this happen?
msg = raw_input('>>>')
if msg == 'exit':
client.send(msg)
break
else:
client.send('<Host>' + msg)
client.close()
client:
# client
import socket
import time
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = 150
client.connect((host,port))
while True:
if client.recv(1024) == 'exit':
print '<System>Host disconnected the Server...'
print '<System>Program will shoot down in 5 seconds'
time.sleep(5)
break
else:
print client.recv(1024)
client.close()
Note that you receive the message twice in the client: First, you receive a message and check whether it's the "exit" message, then a second message is received and printed. Thus, only the even messages are printed, while the odd ones are used up in the if condition.
Try changing the client code to this:
while True:
msg = client.recv(1024)
if msg == 'exit':
print '<System>Host disconnected the Server...'
print '<System>Program will shut down in 5 seconds'
time.sleep(5)
break
else:
print msg