Reputation: 1392
Server in python
import socket
from sys import getsizeof
host = ''
port = 5560
storedValue = "Yo, what's up?"
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
except socket.error as msg:
print(msg)
print("Socket bind comPlete.")
return s
def setupConnection():
s.listen(1) # Allows one connection at a time.
print("Waiting for client")
conn, address = s.accept()
return conn
def GET():
reply = storedValue
return reply
def REPEAT(dataMessage):
reply = dataMessage[1]
return reply
def dataTransfer(conn, s):
# A big loop that sends/receives data until told not to.
while True:
# Receive the data
data = conn.recv(1028) # receive the data
data = data.decode('utf-8')
data = data.strip()
print("data value from client: " + data)
# Split the data such that you separate the command
# from the rest of the data.
command = str(data)
print("data length from client: " + command)
reply = ""
if command == "GET":
reply = GET()
print (command)
print (reply)
elif command == 'REPEAT':
reply = REPEAT(dataMessage)
elif command == 'EXIT':
print("Our client has left us :(")
break
elif command == 'KILL':
print("Our server is shutting down.")
s.close()
break
else:
reply = 'Unknown Command'
# Send the reply back to the client
conn.sendall(bytes(reply, 'utf-8'))
print("Data has been sent!")
conn.close()
s = setupServer()
while True:
try:
conn = setupConnection()
dataTransfer(conn, s)
except:
break
Client in java
import java.io.*;
import java.net.*;
import java.util.*;
public class pcClient {
public static void main(String[] args) {
Socket rpiSocket = null;
DataInputStream in = null;
PrintStream out = null;
try {
rpiSocket = new Socket("localhost",5560);
out = new PrintStream(rpiSocket.getOutputStream());
in = new DataInputStream(new BufferedInputStream(rpiSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: hostname");
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: hostname");
}
try {
if (rpiSocket != null && out != null && in != null) {
while(true) {
System.out.println("Please input your command ");
Scanner scanner = new Scanner(System.in);
String command = scanner.nextLine();
if(command.equals("KILL")) {
break;
}
System.out.println("Sending command to client: " + command);
out.println(command);
byte[] bytes = new byte[1024];
in.read(bytes);
String reply = new String(bytes, "UTF-8");
System.out.println("Reply from server: " + reply.trim());
}
}
rpiSocket.close();
System.out.println("Connections closed successfully");
}
catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
I have the python server above and a java client. The java client takes input from user and sends it to the python. All this is working well. However, the python server is receiving the string from the java and an additional empty string. For example, from the java client, when i send the word "GET", the python server is able to receive this GET and print "Yo, what's up?". However, it goes back to the "While True" and immediately also additionally receives an empty string right after and starts checking the condition with that empty string. I tried to trim the strings received from the java client. How can i solve this? Thanks.
Upvotes: 1
Views: 1346
Reputation: 5387
The problem is occurring because of out.println(command)
you are using from the java program. It is sending the command and also some newline characters over the socket. If you replace it with out.print(command)
, the problem will be solved.
println may be sending the main string and the newline characters internally in two calls, I am not sure. But ideally, every "command" from the client side should first include the length of the command string, and then the real command. Server side may need buffering or splitting of the input data if recv returns more than or less than the required number of bytes.
There is a small python library datachunkpy which may help to split and process the commands (https://pypi.python.org/pypi/datachunkpy/1.0.0)
Upvotes: 1
Reputation: 10959
conn.recv()
returns as much data as immediately available (e.g. one packet). The Java runtime library on the other hand is free to subdivide the sent data into multiple packets. I guess that it sends one packet with the "GET" and another packet with the final newline.
A solution would be for the server to wait and collect input from stream until a newline is found to finish the command.
Upvotes: 1