0

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?

Sfullez
  • 25
  • 7
  • 1
    No, you need to create a protocol to delimit message over the raw byte stream (or re-use an existing protocol). A SOCK_STREAM socket is just as it says, a stream. Sends can be grouped or even split (a single send producing multiple recv). Naive example so you get the idea: you could prepend every message with its size in bytes, so the receiver knows how many bytes to expect. – spectras Jul 06 '17 at 09:46
  • Btw, putting a sleep does not solve your problem. Even with `sleep(15)`, if you get a network lag or if a packet is lost and retransmitted, you will get all data in one `recv`. – spectras Jul 06 '17 at 09:51

1 Answers1

3

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

Tangwz
  • 173
  • 10