So, I have a server sending responses to a client with the socket.send() method. From time to time testing the code on localhost, the socket.recv() method, used by the client to receive the server responses, gets two different messages in one, when the server uses socket.send() twice in a row.
For example:
Server:
from socket import *
serverSocket = socket(AF_INET, SOCK_STREAM)
serverPort = 13005
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
connection_socket, client_ip = serverSocket.accept()
connection_socket.send('Message one')
connection_socket.send('Message two')
Client:
from socket import *
serverName = 'localhost'
serverPort = 13005
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
print clientSocket.recv(1024)
print clientSocket.recv(1024)
The result from running the client, at random times, is
Message oneMessage two
unless I put a sleep(0.1) between the two send(). Is there a way to avoid using sleep? Do I need to put the exact number of bytes to receive in the recv() method?
TCP is a stream oriented protocol and don't send message one by one. A easy way to split the messages that you can set a split string in the end of message like \r\n
Example:
Client:
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 13005
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send('Message one\r\n')
s.send('Message two\r\n')
s.close()
Server:
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 13005
BUFFER_SIZE = 20 # Normally 1024, but we want test
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
data = ''
while 1:
data += conn.recv(BUFFER_SIZE)
if not data: break
if not data.endswith('\r\n'):
continue
lines = data.split('\r\n')
for line in lines:
print line
data = ''
conn.close()
If your message is complicated and long, you can see: Python Socket Receive Large Amount of Data
Related
Hi guys i cant figure out why socket server sends me second message with the third one at the same time. However I want to get message one by one not together at the same time. How can i do this?
Server code:
import socket
host = socket.gethostbyname(socket.gethostname())
port = 5000
ADDR = (host, port)
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
s.bind(ADDR)
s.listen()
c, addr = s.accept()
c.send(b'7:S ACK:4,')
c.send(b'11:S END:kSfdy,')
c.send(b'8:S 120794,')
Client code:
import socket
HOST = '192.168.1.54' # The server's hostname or IP address
PORT = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
print(s.recv(1024))
print(s.recv(1024))
print(s.recv(1024)) #empty message
I make client-sever app. It look like this:
client
import socket
host = '127.0.0.1'
port = 1338
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while True:
st = input("Your message: ")
byt = st.encode()
s.send(byt)
server
import socket
host = ''
port = 1338
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
while True:
s.listen(5)
conn, addr = s.accept()
data = conn.recv(2000)
print(data.decode())
Problem is that only first message is display. How can I solve this problem?
The server receives data only once after accepting a connection from the client. In-order to receive continuously, you can have a while loop for receiving data from the client.
import socket
host = ''
port = 1338
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
while True:
s.listen(5)
conn, addr = s.accept()
condition = True
while condition:
data = conn.recv(2000)
if not data: break
print(data.decode())
So, the above code will receive data as long the user provides data. You can separate the data receiving part in a separate thread too.
As you have the client's connect outside the loop, you have to place the server's listen and accept also outside the loop, since the connection is to be established only once.
I have started to make my own TCP server and client. I was able to get the server and the client to connect over my LAN network. But when I try to have another client connect to make a three way connection, it does not work. What will happen is only when the first connected client has terminated the connection between, the server and the client, can the other client connect and start the chat session. I do not understand why this happens. I have tried threading, loops, and everything else I can think of. I would appreciate any advice. I feel like there is just one small thing i am missing and I can not figure out what it is.
Here is my server:
import socket
from threading import Thread
def whatBeip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 0))
local_ip_address = s.getsockname()[0]
print('Current Local ip: ' + str(local_ip_address))
def clietConnect():
conn, addr = s.accept()
print 'Connection address:', addr
i = True
while i == True:
data = conn.recv(BUFFER_SIZE)
if not data:
break
print('IM Recieved: ' + data)
conn.sendall(data) # echo
whatBeip()
TCP_IP = ''
TCP_PORT = 5005
BUFFER_SIZE = 1024
peopleIn = 4
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(peopleIn)
for client in range(peopleIn):
Thread(target=clietConnect()).start()
conn.close()
Here is my client
import socket
TCP_IP = '10.255.255.3'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
i = True
while i == True:
s.sendall(raw_input('Type IM: '))
data = s.recv(BUFFER_SIZE)
s.close()
This is your main problem: Thread(target=clietConnect()).start() executes the function clientConnect and uses it's return value as the Thread function (which is None, so the Thread does nothing)
Also have a look at:
1) You should wait for all connections to close instead of conn.close() in the end of the server:
threads = list()
for client in range(peopleIn):
t = Thread(target=clietConnect)
t.start()
threads.append(t)
for t in threads: t.join()
and to close the connection when no data is received:
if not data:
conn.close()
return
2) You probably want to use SO_REUSEADDR [ Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems? , Python: Binding Socket: "Address already in use" ]
3) And have a look at asyncio for python
A simple demo of socket programming in python:
server.py
import socket
host = '127.0.0.1'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
while True:
data = conn.recv(1024)
print 'Received:', data
if not data:
break
conn.sendall(data)
print 'Sent:', data
conn.close()
client.py
import socket
host = '127.0.0.1'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall('Hel')
s.sendall('lo world!')
print 'Received:', s.recv(1024)
s.close()
Now code work well. However, the client may not know if server will always send back every time. I tried symmetric code of while-loop in server.py
client_2.py
import socket
host = '127.0.0.1'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall('Hel')
s.sendall('lo world!')
while True:
data = s.recv(1024)
if not data:
break
print 'Received:', data
s.close()
This code will block at
data = s.recv(1024)
But in server.py, if no data received, it will be blank string, and break from while-loop
Why it does not work for client? How can I do for same functionality without using timeout?
You can set a socket to non-blocking operation via socket.setblocking(false), which is equivalent to socket.settimeout(0). Solving this "without using timeout" is impossible.
I just started with socket in python. I set up a basic client-server arrangement in localhost using the following:
for server:
from socket import *
s = socket(AF_INET, SOCK_STREAM)
s.bind(('', 6969))
s.listen(10)
c, a = s.accept()
while c.recv(100000) != '':
print c.recv(100000)
for client:
from socket import *
s = socket(AF_INET, SOCK_STREAM)
s.connect(('localhost', 6969))
while True:
say = raw_input('Input Text: ')
s.send(say)
Now, some data (50 %) is lost when I send it, which means it's not received by the server.
Screenshot :
Why is is so?
Can I do anything to improve the efficiency?
In the server you are calling recv() twice: first in the while loop condition, and then in the body of the loop. Each recv() consumes up to 100000 bytes from the socket, so you are effectively discarding the data from every second read.
Try this instead:
from socket import *
s = socket(AF_INET, SOCK_STREAM)
s.bind(('', 6969))
s.listen(10)
c, a = s.accept()
while True:
data = c.recv(100000)
if data:
print data
else:
print "Client closed connection"
break