I have set up an pi zero running a simple python server script on my local network to respond to certain commands. I am trying to send those commands from an android java app. But when I try to read the reply from the command I have sent it seems like it skipes the line. Because "D/Sending data: Data has been send" is the last thing printed to the log.
This is the nested runnable class I am using to sent a command and then print the reply from the server:
private class SendData implements Runnable
{
private byte[] dataToSend;
private Socket socket;
private OutputStream outputStream;
private BufferedReader bufferedReader;
public SendData(Socket socket, byte[] dataToSend)
{
this.socket = socket;
this.dataToSend = dataToSend;
}
#Override
public void run()
{
try
{
outputStream = socket.getOutputStream();
outputStream.write(dataToSend);
Log.d("Sending data", "Data has been send");
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d("Received", bufferedReader.readLine());
}
catch (IOException e)
{
Log.e("IOException Sending data", e.getMessage());
}
}
}
But when I try to read from the bufferedreader the applications just quits. While the server did sent a reply.
The thread gets started from from this method where "data" is a string.
if (socket != null)
{
Thread sendThread = new Thread(new SendData(socket, data.getBytes()));
Log.d("SocketClient send", "Starting send thread");
sendThread.start();
try
{
sendThread.join();
}
catch (InterruptedException e)
{
Log.d("SocketClient constructor", "Could not join");
}
}
else
{
Log.d("SocketClient send", "Socket is null");
}
Python script running on the pi:
import socket
import sys
from datetime import datetime
host = "192.168.4.1"
port = 12345
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(1)
def data_client(conn, ipStr):
while True:
data = conn.recv(2048)
reply = handle_command(data)
print "Command: %s" % data
if not data or data == "con_close":
print "Connection %s closed" % ipStr
break
conn.send(reply)
print "Send: %s" % reply
conn.close()
def handle_command(cmd):
if (cmd == "con_close"):
return cmd
elif (cmd == "get_time"):
return str(datetime.now())
else:
return "err_invalid_command"
while True:
print "listening:"
conn, addr = sock.accept()
print "Got connection from %s" % addr[0]
data_client(conn, addr[0])
If the receiver tries to read a line then the sender should have send one.
The receiver tries to read a line with readLine() but readLine() never returns as it waits for a newline char that has not been sent.
Related
I created 2 Java programs with sockets in it. I want the client to send continuous data to the server. But after the message sent to the server, the client keeps sending 'null' value to the server (it happens when I close the socket in client program).
Here is my codes:
import ...
public class MainClient {
private Socket serverSock;
private PrintStream clientOutput;
public static void main(String[] args) {
MainClient client = new MainClient();
client.runClient();
}
public void runClient() {
try {
serverSock = new Socket("127.0.0.1",8282);
clientOutput = new PrintStream(serverSock.getOutputStream());
clientOutput.println("Hello, I'm Connected.");
for (int i=0;i<5;i++) {
clientOutput.println(i + "");
clientOutput.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// try {
// serverSock.close(); It will keeps sending 'null' data to the server if I use this line.
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}
The Server Side:
public class MainServer {
private ServerSocket serverSocket;
private int listenPort = 8282;
private InputStream inps;
private Socket clientSocket;
private BufferedReader clientInput;
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(clientSocket.isConnected()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
}
}catch(IOException ex) {
ex.printStackTrace();
}finally {
try {
clientSocket.close();
} catch (IOException e) {}
}
}
public static void main(String[] args) {
new MainServer();
}
}
I tried to close the OutputStream on the Client side with clientOutput.close(); but it sends nulls to the server after it sends the 0-4 loop.
To make it stop and avoid the client sends null data, i should not insert the serverSock.close(); on the Client, but it will returns SocketException. I wanted the client to send 'Closed' message after its done.
Summary, the output on the server is:
Client: 0
Client: 1
Client: 2
Client: 3
Client: 4
Client: null
Client: null
//And so on..
I think there is something missing on the Client Program, i guess?
Thank you for the help :)
As the comment noted, the client is not sending a null value.
The isConnected() method does not do what you think it does, namely it does not tell you if the socket is currently "connected" to its peer, at least in the way you think it should. isConnected() becomes true as soon as the socket transitions into the connected state, and stays true thereafter, even after the socket is shutdown. See this discussion and others on stackoverflow.
The correct way to determine if the peer has shutdown the connection is to attempt to read from the socket and then examine the result for evidence of closure. Please read the Javadocs for the method you are using, they will tell you what the various return values mean. For the BufferedReader.readLine() method, it says:
Returns:
A String containing the contents of the line, not including
any line-termination characters, or null if the end of the stream has
been reached
Throws:
IOException - If an I/O error occurs
Thus you need to check for a null return value to detect a normal socket closure, and if you receive an IOException that indicates some kind of network anomaly.
Your MainClient() have no problem.
clientSocket.isConnected() function in MainServer() always check the status of the client and which results an infinite loop, so after the message 'client:4', clientInput.readLine() should return 'null'.
So instead of checking the client socket is connected or not you can check the client socket is closed or not using function 'clientSocket.isClosed()'.
replace the while loop in MainServer() with below code,
while(!clientSocket.isClosed()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
if(clientMsg.equals("Closed")){
clientSocket.close();
// serverSocket.close();
}
}
this will help you to close the client socket at the time of receiving 'Closed' message from server and this avoid the infinite execution of while loop as well as null statement printing.
The code "serverSocket.close()" help you to close the server socket and you can use this at 'MainServer()' if you need to stop the port listening.
typically the code should be something similar
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((clientMsg = clientInput.readLine()) != null) {
if(isTerminationString(clientMsg)) {
break;
}
System.out.println("Client : " + clientMsg);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
}
}
}
boolean isTerminationString(String msg) {
return msg.equals("DONE!");
}
where in isTerminationString you check if the msg is a termination msg, the communication protocol should be shared between the client and the server . i gave the example of sending
a DONE message, but it could more complex than that .
as closing the close method on the socket does not guarantee that the socket on the other part gets closed as well, using the isClosed method might not be effective and results in the same problem you have .
I am currently coding a simple TCP chat client-server application which works with sockets. A client connects to the server and as soon as it gets accepted, a new worker thread is created to listen for client input. Connecting to the sever (localhost at port 8818) works fine, but as soon as the worker thread starts listening for more client input after the login a java.net.SocketException: Connection reset is thrown (see stack trace below). I am aware that one possible source of this exception can be a socket that hasn't been closed properly or forcefully by either the server or the client. Therefore, my assumption is that I am not handling the closing of my client socket properly which causes the connection to reset.
What I would like to achieve:
The worker listens for client input, as long as this is not null, requests (e.g. a simple login) are processed, otherwise, the socket is closed (see code excerpts below). My client receives a 'Login Successful' message from the server indicating that my handleLogin() function works, but instead of closing the socket after receiving no more input from the client, the server seems to just reset, even though clientSocket.close() is issued after the while loop.
Server.java
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(serverPort);
while (true) {
// Accept connection(s) from new chat client(s)
System.out.println("SERVER: WAITING TO ACCEPT CLIENT CONNECTIONS ...");
Socket clientSocket = serverSocket.accept();
System.out.println("SERVER: CONNECTION ACCEPTED FROM: " + clientSocket);
// Process client request in separate Thread
WorkerThread worker = new WorkerThread(this, clientSocket);
workerList.add(worker);
worker.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
WorkerThread.java
#Override
public void run() {
try {
handleClientSocket();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void handleLogin(OutputStream outputStream, String[] tokens) throws IOException {
if (tokens.length != 3) {
outputStream.write("LOGIN FAILED!\n".getBytes());
return;
}
// Extract username and password from user input
String username = tokens[1];
String password = tokens[2];
if (username.equals("anna") && password.equals("anna")) {
outputStream.write("Login successful!\n".getBytes());
} else {
outputStream.write("Error logging in!\n".getBytes());
}
}
private void handleClientSocket() throws IOException, InterruptedException {
InputStream inputStream = clientSocket.getInputStream();
this.outputStream = clientSocket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
// THIS IS WHERE THE EXCEPTION OCCURS AFTER CLIENT HAS LOGGED IN SUCCESSFULLY
while ((line = bufferedReader.readLine()) != null) {
String[] tokens = StringUtils.split(line);
if (tokens.length > 0 && tokens != null) {
String command = tokens[0];
// Evaluate the entered command and handle the request accordingly
if ("login".equalsIgnoreCase(command)) {
handleLogin(outputStream, tokens);
}
// process other commands ...
}
}
clientSocket.close(); // POSSIBLY WORNG WAY OF CLOSING THE CLIENT SOCKET?
}
Client.java
import java.io.*;
import java.net.Socket;
public class Client {
private final String serverName;
private final int serverPort;
private Socket mySocket;
private OutputStream serverOut;
private InputStream serverIn;
public Client(String serverName, int serverPort) {
this.serverName = serverName;
this.serverPort = serverPort;
}
private boolean connect() {
try {
mySocket = new Socket(serverName, serverPort);
serverOut = mySocket.getOutputStream();
serverIn = mySocket.getInputStream();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private void login(String username, String password) throws IOException {
String command = "login " + username + " " + password + "\n";
serverOut.write(command.getBytes());
}
public static void main(String[] args) throws IOException {
Client client = new Client("localhost", 8818);
if (client.connect()) {
System.out.println("Connection successful!");
client.login("anna", "anna");
} else {
System.err.println("Connection failed ...");
}
}
}
Stack Trace
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:189)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at WorkerThread.handleClientSocket(WorkerThread.java:70)
at WorkerThread.run(WorkerThread.java:45)
When I test my server with PUTTY (i.e. by connecting to localhost and then issuing commands in PUTTY's terminal), everything works just fine.
I am still fairly new to socket programming, so I also might have a logic flaw here. Any help will be much appreciated as I really would like to continue this project.
Thanks in advance!
The reason of this exception is that you terminated the client once you connected the server, but the server still read something from the stream. The exception occurs. Here is the code I tested:
while (inputStream.available() != 0) {
line = bufferedReader.readLine();
String[] tokens = StringUtils.split(line);
if (tokens.length > 0 && tokens != null) {
String command = tokens[0];
// Evaluate the entered command and handle the request accordingly
if ("login".equalsIgnoreCase(command)) {
handleLogin(outputStream, tokens);
}
// process other commands ...
}
}
change the condition in while loop to check if the inputstream is still available to read.
I am trying to establish communication between a SocketServer (Server) in Java and a Socket (Client) in php.
The client is able to connect to host, the client is able to send a message and the server reads the message successfully. But the problem arises when the SocketServer writes to the Client, the client does not receive the message from the server.
I have read the other questions on the same scenario (java-php socket communication) but i just can't seem to find what is causing the problem.
If i use a Java Socket as a client the communication works perfectly both ways.
The Server :
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
protected ServerSocket socket;
protected final int port = 9005;
protected Socket connection;
protected String command = new String();
protected String responseString = new String();
public void init(){
System.out.println( "Launching Server: " );
try{
socket = new ServerSocket(port);
while(true)
{
// open socket
connection = socket.accept();
System.out.println( "Client Connected " );
// get input reader
InputStreamReader inputStream = new InputStreamReader(connection.getInputStream());
BufferedReader input = new BufferedReader(inputStream);
// get input
command = input.readLine();
// process input
System.out.println("Command: " + command);
responseString = command + " MC2 It Works!";
// get output handler
PrintStream response = new PrintStream(connection.getOutputStream());
// send response
response.println(responseString);
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
The Client :
class Client {
private $address;
private $port;
public function __construct($address, $port){
$this->address = $address;
$this->port = $port;
$this->init();
}
private function init(){
//create socket
if(! $socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'))){
$this->showError("socket create");
};
//establish connection
socket_connect($socket, $this->address, $this->port);
//write to server
$message = "I am a client";
socket_write($socket, $message, strlen($message)); //Send data
echo "Listening to Server\n";
//read from server
if(!$reponse = socket_read($socket, 2048, PHP_NORMAL_READ)){
$this->showError("socket read");
}
//print response
echo "Response from server------------------\n";
echo $reponse;
socket_close($socket);
}
private function showError($message){
echo ("Error: ".$message);
exit(666);
}
}
$address="localhost";$port=9005;
echo "Testing Client Server\n";
$client = new Client($address, $port);
Could someone please guide me to what could be the problem here ?
In server side, the code expects a line(terminated with linefeed), in php You send
socket_write($socket, $message, strlen($message));
Please check the data you send accordingly making sure that you send the linefeed character.
There's a million examples on using Java sockets out there - and every one is the same!
Every one shows a client socket being created, some text being sent, and the socket closed.
I am writing some test code. I want my client to loop round and send quite a few messages. It seems silly to close the client socket each time and re-create, so I thought I would just create one client socket, loop round and send data on the same socket. The thing is though - my server socket does not print out what it has received until the last message has been sent by the client and the client socket closed.
Server:
Socket sock;
ClientConnection client;
ServerSocket ss = new ServerSocket(portNumber);
ss.setSoTimeout(0); // 0=infinite
while (true) {
sock = ss.accept();
client = new ClientConnection(sock);
new Thread(client).start();
// ClientConnection reads from sock, prints, and closes sock
}
ClientConnection (a separate class on the Server side):
public class ClientConnection implements Runnable
{
private Socket m_socket;
private BufferedReader m_in = null;
public ClientConnection(Socket socket)
{
m_socket = socket;
try {
InputStream inStream = socket.getInputStream();
m_in = new BufferedReader(new InputStreamReader(inStream));
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
public String getMessage()
{
String line = null;
StringBuffer completeMessage = new StringBuffer();
try {
while ((line = m_in.readLine()) != null)
{
completeMessage.append(line);
}
}
catch (IOException ioe) {
ioe.printStackTrace();
return "";
}
return completeMessage.toString();
}
public void run()
{
try {
String message = getMessage();
System.out.println("Received: " +message);
}
finally
{
try {
m_socket.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Client:
socket = new java.net.Socket(m_destination, m_portNumber);
outputStream = socket.getOutputStream();
printStream = new java.io.PrintStream(outputStream);
while (more-stuff-to-send)
{
printStream.print(text);
printStream.print("\n");
printStream.flush();
}
prinStream.close();
socket.close();
ClientConnection is created by the server when I start the client, but it does not print what has been sent until the client is done sending.
I feel like I'm missing the point somewhere along the line. Chat examples are quite common, so if I had a chat client then every message it wanted to send to a chat server it would create a client socket, send the message, and close the socket? Just doesn't seem right somehow.
Thank you.
client = new ClientConnection(sock);
You are passing the socket in constructor.
so you shouldn't do:
socket = new java.net.Socket(m_destination, m_portNumber);
just cache that vatiable from contructor as : this.sock = sock;
getting the reader and the writer is ok, also the server is ok.
I would use a Vector to be synchromized queue for sending messages, and the while (more-stuff-to-send) loop would check the queue and id empty than sleep, if has something to send, than pop the first and sent it while he must do stuff, or socket is closed my the client.
I am trying to create a simple HTTP web server in Java. I'm just taking this in baby steps so it's super simplistic. I'm trying to make it so I can read simple input from the Client and output anything from the Server when they are both connected.
After searching around on tutorials on websites, this is what I've done so far:
public class Server
{
public static void main(String[] args) throws Exception
{
boolean listening = true;
ServerSocket server = null;
int port = 2222;
try
{
System.out.println("Server binding to port " + port);
server = new ServerSocket(port);
}
catch(Exception e)
{
System.out.println("Error: " + e);
System.exit(1);
}
System.out.println("Server successfully binded to port " + port);
while(listening)
{
System.out.println("Attempting to connect to client");
Socket client = server.accept();
System.out.println("Successfully connected to client");
new ServerThread(client).start() ;
}
server.close();
}
}
public class ServerThread extends Thread
{
private Socket socket = null ;
public ServerThread(Socket s)
{
this.socket = s ;
}
public void run()
{
InputStream in = socket.getInputStream() ;
OutputStream out = socket.getOutputStream() ;
byte [] message, reply;
while((in.read(message))
{
out.write(reply) ;
}
in.close() ;
out.close() ;
socket.close() ;
}
}
It binds and then hangs after attempting to connect to the client. This is because I'm not sure what you do in the while loop in the ServerThread and what you do with the message and reply variables >_< It's been a long time since I've done Java so take it easy on me!
I have only use this kind of server as a "curiosity", to learn new stuff nothing more because you are reinventing the wheel, security reasons etc... I only had to use it once because I had to communicate a server with a JSON code and no server could be installed.
This code needs more work such us creating a new thread for each request, a better RCF HTTP implementation but it works with your ordinary browser.
I hope this helps.
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class MiniPbxManServer extends Thread {
private final int PORT = 2222;
public static void main(String[] args) {
MiniPbxManServer gtp = new MiniPbxManServer();
gtp.start();
}
public void run() {
try {
ServerSocket server = new ServerSocket(PORT);
System.out.println("MiniServer active "+PORT);
boolean shudown = true;
while (shudown) {
Socket socket = server.accept();
InputStream is = socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line;
line = in.readLine();
String auxLine = line;
line = "";
// looks for post data
int postDataI = -1;
while ((line = in.readLine()) != null && (line.length() != 0)) {
System.out.println(line);
if (line.indexOf("Content-Length:") > -1) {
postDataI = new Integer(line
.substring(
line.indexOf("Content-Length:") + 16,
line.length())).intValue();
}
}
String postData = "";
for (int i = 0; i < postDataI; i++) {
int intParser = in.read();
postData += (char) intParser;
}
out.println("HTTP/1.0 200 OK");
out.println("Content-Type: text/html; charset=utf-8");
out.println("Server: MINISERVER");
// this blank line signals the end of the headers
out.println("");
// Send the HTML page
out.println("<H1>Welcome to the Mini PbxMan server</H1>");
out.println("<H2>GET->"+auxLine+ "</H2>");
out.println("<H2>Post->"+postData+ "</H2>");
out.println("<form name=\"input\" action=\"imback\" method=\"post\">");
out.println("Username: <input type=\"text\" name=\"user\"><input type=\"submit\" value=\"Submit\"></form>");
//if your get parameter contains shutdown it will shutdown
if(auxLine.indexOf("?shutdown")>-1){
shudown = false;
}
out.close();
socket.close();
}
server.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
url: localhost:2222/whatever
I think you're going the right way at a high level. The difference between what you've got and production systems is that they do their polling for input on a socket is done in a different thread so as not to halt the system while waiting for input.
In fact, one of the configuration parameters for a web server is how many clients (threads) to have up and running.
You should always flush data from the server's output stream. The client response may depend on this:
out.flush();
To check for the end of stream, you could use:
int result = 0;
while ((result = in.read(message)) != -1) {
...
Also your reply message does not appear to be initialized, you probably want to resend the client data initially:
reply = message;
The jdk has a simplistic http server included to build embedded http servers. Take a look at this link.