I'm working on a little game that sends location data between a client an server to learn how Sockets work.
The server can send and receive data no problem, and the client can send data, but when the client tries to read in data from the server, the program hangs. (This part is commented out)
Server Code:
public void run() {
try {
serverSocket = new ServerSocket(10007);
} catch (IOException e) {
System.err.println("Could not listen on port: 10007.");
System.exit(1);
}
try {
System.out.println("Waiting for connection...");
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
System.out.println("Connection successful");
System.out.println("Waiting for input.....");
while (true) {
try {
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
if (in.readLine() != "0" && in.readLine() != null) {
setXY(in.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
out.println("X" + Graphics.charX);
out.println("Y" + Graphics.charY);
}
Client Code:
public void run() {
try {
System.out.println("Attemping to connect to host " + serverHostname + " on port " + serverPort + ".");
echoSocket = new Socket(serverHostname, serverPort);
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + "the connection to: " + serverHostname);
System.exit(1);
}
while (true) {
try {
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
out = new PrintWriter(echoSocket.getOutputStream(), true);
/*if (in.readLine() != "0" && in.readLine() != null) {
setXY(in.readLine());
}*/
} catch (IOException e2) {
e2.printStackTrace();
}
out.println("X" + Graphics.charX);
out.println("Y" + Graphics.charY);
}
}
Any help is much appreciated!
You need two threads to read/write blocking sockets at the same time (which is what you're trying to do). When you call in.readLine(), the current thread will block until it receives a line of data.
Related
Hi Stackover flow world,
Thought I'd send something over as I haven't shared a question in some time. I've been pretty stumped on the weirdest, possibly simplest question ever, that I've been finding all sorts of different responses online.
Basically, I have a SimpleServer which looks as so:
// A generic server that listens on a port and connects to any clients it
// finds. Made to extend Thread, so that an application can have multiple
// server threads servicing several ports, if necessary.
public class SimpleServer
{
protected int portNo = 8082; // Port to listen to for clients
protected ServerSocket clientConnect;
public SimpleServer(int port) throws IllegalArgumentException {
if (port <= 0)
throw new IllegalArgumentException(
"Bad port number given to SimpleServer constructor.");
// Try making a ServerSocket to the given port
System.out.println("Connecting server socket to port...");
try { clientConnect = new ServerSocket(port); }
catch (IOException e) {
System.out.println("Failed to connect to port " + port);
System.exit(1);
}
// Made the connection, so set the local port number
this.portNo = port;
}
public static void main(String argv[]) {
int port = 8088;
if (argv.length > 0) {
int tmp = port;
try {
tmp = Integer.parseInt(argv[0]);
}
catch (NumberFormatException e) {}
port = tmp;
}
SimpleServer server = new SimpleServer(port);
System.out.println("SimpleServer running on port " + port + "...");
server.listen();
}
public void listen() {
// Listen to port for client connection requests.
try {
System.out.println("Waiting for clients...");
while (true) {
Socket clientReq = clientConnect.accept();
System.out.println("Got a client...");
serviceClient(clientReq);
}
}
catch (IOException e) {
System.out.println("IO exception while listening for clients.");
System.exit(1);
}
}
public void serviceClient(Socket clientConn) {
SimpleCmdInputStream inStream = null;
DataOutputStream outStream = null;
try {
inStream = new SimpleCmdInputStream(clientConn.getInputStream());
outStream = new DataOutputStream(clientConn.getOutputStream());
}
catch (IOException e) {
System.out.println("SimpleServer: Error getting I/O streams.");
}
SimpleCmd cmd = null;
System.out.println("Attempting to read commands...");
while (cmd == null || !(cmd instanceof DoneCmd)) {
try { cmd = inStream.readCommand(); }
catch (IOException e) {
System.out.println("SimpleServer: " + e);
System.exit(1);
}
if (cmd != null) {
String result = cmd.Do();
try { outStream.writeBytes(result); }
catch (IOException e) {
System.out.println("SimpleServer: " + e);
System.exit(1);
}
}
}
}
public synchronized void end() {
System.out.println("Shutting down SimpleServer running on port "
+ portNo);
}
}
Then I have a SimpleClient which looks as so:
public class SimpleClient
{
// Our socket connection to the server
protected Socket serverConn;
// The input command stream from the server
protected SimpleCmdInputStream inStream;
public SimpleClient(String host, int port)
throws IllegalArgumentException {
try {
System.out.println("Trying to connect to " + host + " " + port);
serverConn = new Socket(host, port);
}
catch (UnknownHostException e) {
throw new IllegalArgumentException("Bad host name given.");
}
catch (IOException e) {
System.out.println("SimpleClient: " + e);
System.exit(1);
}
System.out.println("Made server connection.");
}
public static void main(String argv[]) {
if (argv.length < 2) {
System.out.println("Usage: java SimpleClient [host] [port]");
System.exit(1);
}
System.out.println("Getting here");
String host = argv[0];
int port=0;
try {
port = Integer.parseInt(argv[1]);
}
catch (NumberFormatException e) {}
SimpleClient client = new SimpleClient(host, port);
System.out.println("Commands are about to send?");
client.sendCommands();
}
public void sendCommands() {
try {
OutputStreamWriter wout =
new OutputStreamWriter(serverConn.getOutputStream());
BufferedReader rin = new BufferedReader(
new InputStreamReader(serverConn.getInputStream()));
wout.write("what is a man is a good man\n");
wout.flush();
rin.readLine();
System.out.println("getting here yo");
// Send a GET command...
wout.write("GET goodies ");
// ...and receive the results
String result = rin.readLine();
System.out.println(result + "I am here");
System.out.println("Server says: \"" + result + "\"");
// Now try a POST command
wout.write("POST goodies ");
// ...and receive the results
result = rin.readLine();
System.out.println("Server says: \"" + result + "\"");
// All done, tell the server so
wout.write("DONE ");
result = rin.readLine();
System.out.println("Server says: \"" + result + "\"");
}
catch (IOException e) {
System.out.println("SimpleClient: " + e);
System.exit(1);
}
}
public synchronized void end() {
System.out.println("Closing down SimpleClient...");
try { serverConn.close(); }
catch (IOException e) {
System.out.println("SimpleClient: " + e);
System.exit(1);
}
}
}
Connected to the target VM, address: '127.0.0.1:64335', transport: 'socket'
Getting here
Trying to connect to localhost 8088
Made server connection.
Commands are about to send?
Output
Connected to the target VM, address: '127.0.0.1:64335', transport: 'socket'
Getting here
Trying to connect to localhost 8088
Made server connection.
Commands are about to send?
For some reason the client freezes at 'commands are about to send', and for some reason doesn't truly 'write' to the socket when sending these commands to the server.
Any clues, am i missing something, completely off the mark here?
Thanks!
Arsalan
Figured it out, seems like there's so much drama when it comes to all the types of streams, writers, readers, etc. It seems that somehow my samples have used the types of these streams incorrectly, as the clear difference to understand is that streams are for everything that implement Output or Input Stream, and are for essentially for reading or writing binary data.
Readers & writers are a layer above streams for reading and writing text. Readers and writers convert binary data from and to characters using a character encoding.
Basically now do this in my SimpleClient
public class SimpleClient
{
// Our socket connection to the server
protected Socket serverConn;
// The input command stream from the server
protected SimpleCmdInputStream inStream;
public SimpleClient(String host, int port)
throws IllegalArgumentException {
try {
System.out.println("Trying to connect to " + host + " " + port);
serverConn = new Socket(host, port);
}
catch (UnknownHostException e) {
throw new IllegalArgumentException("Bad host name given.");
}
catch (IOException e) {
System.out.println("SimpleClient: " + e);
System.exit(1);
}
System.out.println("Made server connection.");
}
public static void main(String argv[]) {
if (argv.length < 2) {
System.out.println("Usage: java SimpleClient [host] [port]");
System.exit(1);
}
System.out.println("Getting here");
String host = argv[0];
int port=0;
try {
port = Integer.parseInt(argv[1]);
}
catch (NumberFormatException e) {}
SimpleClient client = new SimpleClient(host, port);
client.sendCommands();
}
public void sendCommands() {
try {
DataOutputStream wout =
new DataOutputStream(serverConn.getOutputStream());
DataInputStream rin = new DataInputStream(serverConn.getInputStream());
// Send a GET command...
wout.writeChars("GET goodies ");
// ...and receive the results
String result = rin.readLine();
System.out.println("Server says: \"" + result + "\"");
// Now try a POST command
wout.writeChars("POST goodies ");
// ...and receive the results
result = rin.readLine();
System.out.println("Server says: \"" + result + "\"");
// All done, tell the server so
wout.writeChars("DONE ");
result = rin.readLine();
System.out.println("Server says: \"" + result + "\"");
}
catch (IOException e) {
System.out.println("SimpleClient: " + e);
System.exit(1);
}
}
public synchronized void end() {
System.out.println("Closing down SimpleClient...");
try { serverConn.close(); }
catch (IOException e) {
System.out.println("SimpleClient: " + e);
System.exit(1);
}
}
}
Notice the new type of the output and input streams, rather than writers.
Thanks Arsalan!
I have used both a reader object and a scanner but while this client is connected to a simple socket server and they are both running, I cannot take an input from the user in the console and pass it to the server. pressing enter simply skips a line, scanner.nextLine() seems to capture nothing or something is going wrong when passing a variable to the output streamer.
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
Socket socket = null;
DataOutputStream outputStream = null;
BufferedReader reader = null;
Scanner scan = new Scanner(System.in);
String message;
String host = "macbook";
int port = 9999;
//attempts to connect to given host and port
try {
socket = new Socket(host, port);
outputStream = new DataOutputStream(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + host +".");
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + host+".");
e.printStackTrace();
}
// if everything has been initialized then write some data
if (socket != null && outputStream != null && reader != null) {
try {
message=scan.nextLine();
outputStream.writeBytes(message);
String responseLine;
while ((responseLine = reader.readLine()) != null) {
System.out.println("Server: " + responseLine);
if (responseLine.indexOf("Ok") != -1) {
break;
}
}
//closes client once communication with server has ended
outputStream.close();
reader.close();
socket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to unknown host: " + e);
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
}
I coded a server application that constantly listens to data being sent to it. I took multi-threading into consideration by the way. I have the main thread, writer thread, and reader thread. When I launch the program, everything works perfectly. After about 15 minutes of up-time though, my CPU usage just randomly skyrockets. I believe it reaches about 40% just for the server application if I remember correctly. I think I'm doing something wrong with networking since this is my first time working with sockets.
This is what I use to read data:
public void run(){
Socket s = null;
InputStream in = null;
while (Main.running){
try {
s = network.getServerSocket().accept();
in = s.getInputStream();
} catch (IOException e){
e.printStackTrace();
}
if (in != null){
DataInputStream input = new DataInputStream(in);
try {
while (input.available() != -1) {
byte type = input.readByte();
PacketIn packet = Utils.getPacket(main, type);
packet.readData(input);
if (packet instanceof PacketInLogin) {
PacketInLogin login = (PacketInLogin) packet;
login.setSocket(s);
String server = login.getServer();
Socket socket = login.getSocket();
Main.log("Login request from server: '" + server + "'. Authenticating...");
boolean auth = login.authenticate();
Main.log("Authentication test for server: '" + server + "' = " + (auth ? "PASSED" : "FAILED"));
if (auth) {
main.getServers().put(server, new DataBridgeServer(main, server, socket));
}
main.getTransmitter().sendPacket(new PacketOutAuthResult(main, auth), socket);
} else if (packet instanceof PacketInDisconnect) {
PacketInDisconnect disconnect = (PacketInDisconnect) packet;
main.getServers().remove(disconnect.getServer().getName());
Main.log("'" + disconnect.getServer().getName() + "' has disconnected from network.");
}
}
} catch (IOException e){
if (!(e instanceof EOFException)){
e.printStackTrace();
}
} finally {
if (in != null){
try {
in.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
}
try {
if (s != null) s.close();
if (in != null) in.close();
} catch (IOException e){
e.printStackTrace();
}
}
This is what I use to write data (to the client. This code is still part of the server):
public void run(){
while (Main.running){
if (!QUEUED.isEmpty()){
PacketOut packet = (PacketOut) QUEUED.keySet().toArray()[0];
Socket server = QUEUED.get(packet);
DataOutputStream out = null;
try {
out = new DataOutputStream(server.getOutputStream());
packet.send(out);
} catch (IOException e){
e.printStackTrace();
} finally {
if (out != null){
try {
out.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
QUEUED.remove(packet);
}
}
}
I made an app client in android device (with ethernet and wireless port) and server application in windows.
Data transfers via Socket programming between devices and when i test it in emulator in PC or run in Ethernet via cable it works correctly, but when i connect server and client with wireless connectivity (via an access point) data sent or received with a delay . this delay may be take over 60 seconds !
i don't know why this problem happend !
This is my sending routin in android :
Server_Port = mDbHelper.GetPortNumber();
//mDbHelper.close();
final String Concatinate_values = firstByte_KindType + Spliter + secoundByte_KindofMove +
Spliter + ValueOfMove + Spliter + valueOfsetting + Spliter + MaxOrMinValue;
//Sent Routin
////‌Connect To server
Thread thread = null;
thread = new Thread(new Runnable() {
#Override
public void run() {
DataOutputStream outputStream = null;
BufferedReader inputStream = null;
Socket socket;
socket = new Socket();
try {
socket.connect(new InetSocketAddress(Server_IP, Server_Port), 10);
}
catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
Thread.currentThread().interrupt();
}
////Make Read Line
try {
outputStream = new DataOutputStream(socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (IOException e1) {
//Finished Socket
ShutDown(socket);
}
if (outputStream == null) {
//
ShutDown(socket);
Thread.currentThread().interrupt();
return;
}
//Write Message
try {
String message = Concatinate_values + "\n";
outputStream.write(message.getBytes());
outputStream.flush();
ShutDown(socket);
Thread.currentThread().interrupt();
return;
}
catch (IOException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
try {
if (socket != null) {
socket.close();
}
}
catch (IOException e) {
e.printStackTrace();
ShutDown(socket);
Thread.currentThread().interrupt();
return;
}
Thread.currentThread().interrupt();
}
});
thread.start();
My windows server code in c# :
class Program
{
static Socket socketForClient;
static NetworkStream networkStream;
static System.IO.StreamReader streamReader;
static System.IO.StreamWriter streamWriter;
static TcpListener tcpListener;
static int PORT;
static void Main(string[] args)
{
//Console.WriteLine("Enter Port : ");
//PORT = Convert.ToInt32(Console.ReadLine());
PORT = 12500;
Console.WriteLine("\n" + "Your Host Information Is : "+"\n" );
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
foreach (IPAddress ip in localIPs)
{
Console.WriteLine(ip.ToString());
}
while (true)
{
tcpListener = new TcpListener(PORT);
Console.WriteLine("\n >> Server started ... Waiting for Message");
tcpListener.Start();
try
{
socketForClient = tcpListener.AcceptSocket();
}
catch (System.Exception e1)
{
Console.WriteLine("LN: 40");
Console.WriteLine("Message: " + e1.Message);
Console.WriteLine("InnerException: " + e1.InnerException);
Console.WriteLine("Source: " + e1.Source);
Console.ReadLine();
}
if (socketForClient.Connected)
{
Console.WriteLine("Client connected");
try
{
networkStream = new NetworkStream(socketForClient);
}
catch (System.Exception e1)
{
Console.WriteLine("LN: 55");
Console.WriteLine("Message: " + e1.Message);
Console.WriteLine("InnerException: " + e1.InnerException);
Console.WriteLine("Source: " + e1.Source);
Console.ReadLine();
}
//System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
try
{
streamReader = new System.IO.StreamReader(networkStream);
streamWriter = new System.IO.StreamWriter(networkStream);
}
catch (System.Exception e1)
{
Console.WriteLine("LN: 71");
Console.WriteLine("Message: " + e1.Message);
Console.WriteLine("InnerException: " + e1.InnerException);
Console.WriteLine("Source: " + e1.Source);
Console.ReadLine();
}
string theString = "Sending";
// streamWriter.WriteLine(theString);
Console.WriteLine(theString);
//streamWriter.Flush();
long x = 0;
try
{
x++;
theString = streamReader.ReadLine();
if (theString.Trim() == "4-")
{
Console.WriteLine("Sending Report Data : 0-100-0-0");
streamWriter.WriteLine("0-70-0-0");
Console.WriteLine("pocket sent");
streamWriter.Flush();
}
Console.WriteLine(theString + x.ToString());
streamReader.Close();
networkStream.Close();
socketForClient.Close();
tcpListener.Stop();
}
catch (System.Exception e1)
{
streamReader.Close();
networkStream.Close();
socketForClient.Close();
Console.WriteLine("LN: 97");
Console.WriteLine("Message: " + e1.Message);
Console.WriteLine("InnerException: " + e1.InnerException);
Console.WriteLine("Source: " + e1.Source);
Console.ReadLine();
break;
//streamWriter.Close();
}
}
}
streamReader.Close();
networkStream.Close();
socketForClient.Close();
Console.WriteLine("Closed Socket");
Console.ReadLine();
}
}
I'm new to android, java and socket programming so of course I'm trying to merge all three!
I'm creating a desktop based java server which will simply send a short string to an android app(client).
I have the android app running fine and it sends strings to the server which are read with no problems.
I have the server running and it recieves the strings with no problems.
The app(client) however has a socket timeout whenever I try to read the strings returned from the server. I'm using the same code so I can't understand the problem.
Anyway here's the code:
//SERVER//
import java.io.*;
import java.net.*;
import java.util.*;
public class GpsServer {
ServerSocket serversocket = null;
Socket socket = null;
public GpsServer()
{
try
{
serversocket = new ServerSocket(8189);
}
catch (UnknownHostException unhe)
{
System.out.println("UnknownHostException: " + unhe.getMessage());
}
catch (InterruptedIOException intioe)
{
System.out.println("Timeout while attempting to establish socket connection.");
} catch (IOException ioe)
{
System.out.println("IOException: " + ioe.getMessage());
}
}
public void refreshServer() {
try
{
socket = serversocket.accept();
InputStreamReader inputstreamreader = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
PrintWriter printwriter = new PrintWriter(socket.getOutputStream(),true);
System.out.println("socket read successful");
printwriter.println("Send Bye to disconnect.");
String lineread = "";
boolean done = false;
while (((lineread = bufferedreader.readLine()) != null) && (!done)){
System.out.println("Received from Client: " + lineread);
printwriter.println("You sent: " + lineread);
if (lineread.compareToIgnoreCase("Bye") == 0) done = true;
}
System.out.println("Closing connection");
socket.close();
bufferedreader.close();
inputstreamreader.close();
printwriter.close();
}
catch (UnknownHostException unhe)
{
System.out.println("UnknownHostException: " + unhe.getMessage());
}
catch (InterruptedIOException intioe)
{
System.out
.println("Timeout while attempting to establish socket connection.");
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe.getMessage());
}
}
public void nullify() {
try
{
socket.close();
serversocket.close();
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe.getMessage());
}
}
}
and the client...
//CLIENT
import java.io.*;
import java.net.*;
import java.util.*;
public class GpsClient {
public String lastMessage;
Socket socket = null;
String serverurl;
int serverport;
public GpsClient() {
lastMessage = "";
serverport = 8189;
serverurl = "192.168.10.4";
try
{
socket = new Socket(serverurl, serverport);
socket.setSoTimeout(10000);
}
catch (UnknownHostException unhe)
{
System.out.println("UnknownHostException: " + unhe.getMessage());
}
catch (InterruptedIOException intioe)
{
System.out.println("Timeout while attempting to establish socket connection.");
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe.getMessage());
}
}
public void retrieveNew() {
try {
socket = new Socket(serverurl, serverport);
socket.setSoTimeout(10000);
lastMessage = "connected!";
InputStreamReader inputstreamreader = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
PrintWriter printwriter = new PrintWriter(socket.getOutputStream(),true);
printwriter.println("Request");
lastMessage = "Request sent";
// Get error when I uncomment this block, i.e. try to read the response from the server
// "Timeout while attempting to establish socket connection."
// String lineread = "";
// while ((lineread = bufferedreader.readLine()) != null) {
// System.out.println("Received from Server: " + lineread);
// lastMessage = "Received from Server: " + lineread;
// }
lastMessage = "closing connection!";
bufferedreader.close();
inputstreamreader.close();
printwriter.close();
socket.close();
}
catch (UnknownHostException unhe)
{
System.out.println("UnknownHostException: " + unhe.getMessage());
}
catch (InterruptedIOException intioe)
{
System.out.println("Timeout while attempting to establish socket connection.");
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe.getMessage());
}
finally
{
try
{
socket.close();
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe.getMessage());
}
}
}
public void nullify() {
try
{
PrintWriter printwriter = new PrintWriter(socket.getOutputStream(),true);
printwriter.println("Bye");
printwriter.close();
socket.close();
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe.getMessage());
}
}
}
Thanks in advance!
Josh
Apart from all the issues noted in my comment, you are creating two sockets in the client, and your server is only written to process one connection. So it writes to the first one and tries to read from it, meanwhile your client is writing to the second one and trying to read from that.
When you fix that you will then hit a deadlock, as both sides are trying to read from each other.
Also you shouldn't use PrintWriter or PrintStream over the network, as they swallow exceptions you need to know about. Use BufferedWriter.
Try putting something at the end of the server message, like ETX or something like <end> or wrap the message in <msg>...</msg>.
Then on Android in the while loop check if you received it instead of checking (lineread = bufferedreader.readLine()) != null.