I am trying to send accelerator values over bluetooth from an Android App to the PC. I am working on the BluetoothChat demo application. In the Android App I have a method called onSensorChanged that will be called every time when the accelerations changes. the method looks like below:
#Override
public void onSensorChanged(SensorEvent e) {
// the work done when the accelerometer data changes
try {
Thread.sleep(25);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
sensorX = e.values[0];
sensorY = e.values[1];
Toast.makeText(BluetoothChat.this, "x coordinate = " + sensorX + "y coordinate = " + sensorY Toast.LENGTH_SHORT).show();
BigDecimal sensorXDec = new BigDecimal(e.values[0]).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal sensorYDec = new BigDecimal(e.values[1]).setScale(2,BigDecimal.ROUND_HALF_UP);
String vals = String.valueOf(sensorXDec.toPlainString() + "," + sensorYDec.toPlainString());
mChatService.writeFromString(vals);
}
The method writeFromString
public void writeFromString(String temp){
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.writeString(temp);
}
and the writeString method is the following:
public void writeString(String out) {
try {
if(D) Log.d(TAG, "Sending File....AS STRING");
mmOutStream.write(out.getBytes(), 0, out.getBytes().length);
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
in the following method I process the inputStream on the PC side
#Override
public void run() {
try {
// prepare to receive data
InputStream inputStream = mConnection.openInputStream();
System.out.println("waiting for input");
while (true) {
int command = inputStream.read();
if (command == EXIT_CMD)
{
System.out.println("finish process");
break;
}
processCommand(command);
}
} catch (Exception e) {
e.printStackTrace();
}
}
The question again is: How can I retrieve each set of Strings I am sending from the Android App?
Try this
String msg = null;
BufferedReader br = new BufferedReader(
new InputStreamReader(inputStream)
);
msg = br.readLine();
This will solve problem
Scanner scanner = new Scanner (inputStream);
while(true){
if(!scanner.hasNextInt()){
continue;
}
// at this point we've got an int, so get it and use it
try{
int commmand = scanner.nextInt();
if (command == EXIT_CMD){
System.out.println("finish process");
break;
}
processCommand(command);
} catch (Exception catchThem){
// Deal with the caught exceptions
}
}
I didn't test this, hope it works for you.
Related
I have to create a simple rotating proxy application where 100 requests get evenly distributed to 10 devices. I've got the following structure:
WebServer with a Java-SocketServer running. All Android devices are connected to this Socket-Server to be able to know which devices are currently online and for determining which device should be used for the next request.
10 Android devices in different networks. They are connected to the Socket Server and are waiting for requests that should be forwarded to the remote address and then sent back to the SocketServer.
In easy words: I basically have to create an application similar like Honeygain, Peer2Profit or IPRoyal Pawns so that I can later do requests like this:
//Use "-x" to set Proxy-IP and Proxy-Port
curl -x ANDROID_DEVICE_IP:PORT -L https://www.google.com
I managed to have an always running proxy service in an Android application. It basically looks like this and just forwards HTTP-Requests from Port 1440 to the desired remote address and then sends the response back to the original client. The Proxy basically works fine.
public class ProxyServerThread extends Thread {
public static void main(String[] args) {
(new ProxyServerThread()).run();
}
public ProxyServerThread() {
super("Server Thread");
}
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(1440)) {
Socket socket;
try {
while ((socket = serverSocket.accept()) != null) {
(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
return;
}
}
public static class Handler extends Thread {
public static final Pattern CONNECT_PATTERN = Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])", Pattern.CASE_INSENSITIVE);
private final Socket clientSocket;
private boolean previousWasR = false;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
String request = readLine(clientSocket);
System.out.println(request);
Matcher matcher = CONNECT_PATTERN.matcher(request);
if (matcher.matches()) {
String header;
do {
header = readLine(clientSocket);
} while (!"".equals(header));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(clientSocket.getOutputStream(), "ISO-8859-1");
final Socket forwardSocket;
try {
forwardSocket = new Socket(matcher.group(1), Integer.parseInt(matcher.group(2)));
System.out.println(forwardSocket);
} catch (IOException | NumberFormatException e) {
e.printStackTrace(); // TODO: implement catch
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 502 Bad Gateway\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
return;
}
try {
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 200 Connection established\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
Thread remoteToClient = new Thread() {
#Override
public void run() {
forwardData(forwardSocket, clientSocket);
}
};
remoteToClient.start();
try {
if (previousWasR) {
int read = clientSocket.getInputStream().read();
if (read != -1) {
if (read != '\n') {
forwardSocket.getOutputStream().write(read);
}
forwardData(clientSocket, forwardSocket);
} else {
if (!forwardSocket.isOutputShutdown()) {
forwardSocket.shutdownOutput();
}
if (!clientSocket.isInputShutdown()) {
clientSocket.shutdownInput();
}
}
} else {
forwardData(clientSocket, forwardSocket);
}
} finally {
try {
remoteToClient.join();
} catch (InterruptedException e) {
e.printStackTrace(); // TODO: implement catch
}
}
} finally {
forwardSocket.close();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
}
private static void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[4096];
int read;
do {
read = inputStream.read(buffer);
if (read > 0) {
outputStream.write(buffer, 0, read);
if (inputStream.available() < 1) {
outputStream.flush();
}
}
} while (read >= 0);
} finally {
if (!outputSocket.isOutputShutdown()) {
outputSocket.shutdownOutput();
}
}
} finally {
if (!inputSocket.isInputShutdown()) {
inputSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
private String readLine(Socket socket) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int next;
readerLoop:
while ((next = socket.getInputStream().read()) != -1) {
if (previousWasR && next == '\n') {
previousWasR = false;
continue;
}
previousWasR = false;
switch (next) {
case '\r':
previousWasR = true;
break readerLoop;
case '\n':
break readerLoop;
default:
byteArrayOutputStream.write(next);
break;
}
}
return byteArrayOutputStream.toString("ISO-8859-1");
}
}
}
Here comes the Problem:
Everything works fine but only on the local network. I cannot manage to get this to work without port forwarding. Since all devices are on their mobile cellular data I need a way to be able to connect to the device anyway.
How do the mentioned apps manage to connect to the devices?
I am writing a java program that will need to run a python script.
The script will print output which will java need to read to know the progress of the script.
To be able to pause the script while running I want it to ask for input once in a while, only when java give it input the script will keep going.
Here is my Java method:
private static void sevenTry(String[] strCommands) throws IOException {
Object oLock1 = new Object();
Object oLock2 = new Object();
ProcessBuilder pBuilder = new ProcessBuilder(strCommands);
pBuilder.redirectErrorStream(true);
Process proc = pBuilder.start();
Thread tReader = new Thread() {
#Override
public void run() {
System.out.println("~~tReader starting~~");
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
synchronized (oLock1) {
try {
String line = reader.readLine();
while (line != null && !line.trim().equals("--EOF--")) {
System.out.println("Stdout: " + line);
if (line.trim().equals("--INPUT--")) {
synchronized (oLock2) {
oLock2.notify();
}
oLock1.wait();
}
line = reader.readLine();
}
} catch (IOException e) {
System.out.println("tReader: " + e.getMessage());
} catch (InterruptedException e) {
System.out.println("tReader: " + e.getMessage());
} catch (Exception e) {
System.out.println("tReader: " + e.getMessage());
}
}
System.out.println("~~tReader end~~");
synchronized (oLock2) {
oLock2.notify();
}
}
};
Thread tWriter = new Thread() {
#Override
public void run() {
System.out.println("~~tWriter starting~~");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
String line, input;
Scanner scan = new Scanner(System.in);
synchronized (oLock2) {
try {
oLock2.wait();
} catch (InterruptedException e1) {
System.out.println("tWriter: " + e1.getMessage());
}
}
while (tReader.isAlive()) {
synchronized (oLock1) {
System.out.println("Java: insert input");
scan.hasNext();
input = scan.nextLine();
try {
writer.write(input + "\n");
writer.flush();
} catch (IOException e) {
System.out.println("tWriter: " + e.getMessage());
}
oLock1.notify();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
System.out.println("tWriter: " + e1.getMessage());
}
}
System.out.println("~~tWriter end~~");
}
};
tReader.start();
tWriter.start();
System.out.println("~~everything submitted~~");
try {
tReader.join();
tWriter.join();
System.out.println("~~finish~~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This is my python script:
# coding=utf-8
import sys
print '1'
print '--INPUT--'
inum = sys.stdin.readline()
print '2'
print '--EOF--'
I tried running my code
sevenTry("python", "C:\\Testing.py");
but on java side it get stuck inside tReader at line:
String line = reader.readLine();
The program does work if i take out the input line from the python file
inum = sys.stdin.readline()
Using
inum = raw_input()
still bring up the same problem (im using python 2.7)
The most confusing part here that i even tried to test this with a java file (instead of python)
sevenTry("java", "-classpath", "C:\\class", "CheckCMD");
and it worked even with the input lines
import java.util.Scanner;
public class CheckCMD {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String line;
System.out.println("1");
System.out.println("--INPUT--");
in.hasNext();
line = in.nextLine();
System.out.println("2");
System.out.println("--EOF--");
}
}
As you may have noticed, this is a problem related to Python.
As described in https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately,
" when process STDOUT is redirected to something other than a terminal, then the output is buffered into some OS-specific-sized buffer (perhaps 4k or 8k in many cases)."
So, you need to call sys.stdout.flush() after each invoke to print.
Or, as a better option, you can change the default behaviour for the process, using the -u param, to get unbuffered output.
I have implemented a program to receive call using gsm modem. Upon Detecting "RING" call is answered an audio clip is played by calling a function from inside DATA_AVAILABLE EVENT HANDLER. But the event handler stops working after this. After the audio is complete Event Handler does not show any data received event anymore.
Why does the event listener stops working. Am I doing it wrong by playing the audio from inside the event handler? I was thinking about setting a variable true or false from inside data_received event handler and create custom event handler to listen to change to that variable to do playback of audio can these both work simultaneously in anyway?
How to create a multi threading solution So that Serial I/O is not interrupted and Audio Playback and Audio Sampling Can be done in a synchronised manner to detect dtmf tones.
Is there any way that serial port events can be listened to constantly without interruption and run a function for audio sampling and audio playback at specific time
Call Accepted in this case of switch and thread is started inside play() function
case SerialPortEvent.DATA_AVAILABLE:
StringBuffer sb = new StringBuffer();
byte[] readBuffer = new byte[2048];
try {
while (inputStream.available() > 0)
{
int numBytes = inputStream.read(readBuffer);
sb.append(new String(readBuffer,0,numBytes));
System.out.println(numBytes);
System.out.println(sb);
}
System.out.println("Data Available");
if((sb.toString()).contains("RING")){
System.out.println("Enter Inside if RING Loop");
//play();
send("ATA\r\n");
//welcomeMessage();
}
if((sb.toString()).contains("CARRIER")){
hangup();
//Thread.sleep(1000);
closePort();
outCommand();
System.out.println("Enter Inside if NO CARRIER Loop");
}
//print response message
System.out.print(sb.toString());
} catch (IOException e) {
}
break;
public void play() {
try {
new Thread() {
public void run() {
for(int i=0;i<1;i++)
welcomeMessage();
}
}.start();
} catch (Throwable e) {
e.printStackTrace();
}
}
Full Code
package sample;
import java.io.*;
import java.util.*;
import javax.sound.sampled.*;
import javazoom.jl.player.*;
import java.io.FileInputStream;
import gnu.io.*;
import java.io.*;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.apache.log4j.chainsaw.Main;
import sun.audio.*;
public class GSMConnect implements SerialPortEventListener,
CommPortOwnershipListener {
private static String comPort = "COM3"; // This COM Port must be connect with GSM Modem or your mobile phone
private String messageString = "";
private CommPortIdentifier portId = null;
private Enumeration portList;
private InputStream inputStream = null;
private OutputStream outputStream = null;
private SerialPort serialPort;
String readBufferTrial = "";
/** Creates a new instance of GSMConnect */
public GSMConnect(String comm) {
this.comPort = comm;
}
public boolean init() {
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
if (portId.getName().equals(comPort)) {
System.out.println("Got PortName");
return true;
}
}
}
return false;
}
public void checkStatus() {
send("AT+CREG?\r\n");
}
public void dial(String phoneNumber) {
try {
//dial to this phone number
messageString = "ATD" + phoneNumber + ";\r\n";
outputStream.write(messageString.getBytes());
System.out.println("Called ");
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(String cmd) {
try {
outputStream.write(cmd.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String phoneNumber, String message) {
char quotes ='"';
send("AT+CMGS="+quotes + phoneNumber +quotes+ "\r\n");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// send("AT+CMGS=\""+ phoneNumber +"\"\r\n");
send(message + '\032');
System.out.println("Message Sent");
}
public void hangup() {
send("ATH\r\n");
}
public void welcomeMessage(){
// open the sound file as a Java input stream
String gongFile = "C:\\Users\\XXXX\\Desktop\\1-welcome.wav";
}*/
try{
FileInputStream fis = new FileInputStream("C:\\Users\\XXXX\\Desktop\\7001110.mp3");
Player playMP3 = new Player(fis);
playMP3.play();
System.out.print("welcomeMessage() Read");
}catch(Exception e){
System.out.println(e);
}
}
public void play() {
try {
new Thread() {
public void run() {
for(int i=0;i<1;i++)
welcomeMessage();
}
}.start();
} catch (Throwable e) {
e.printStackTrace();
}
}
public void connect() throws NullPointerException {
if (portId != null) {
try {
portId.addPortOwnershipListener(this);
serialPort = (SerialPort) portId.open("MobileGateWay", 2000);
serialPort.setSerialPortParams(115200,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
} catch (PortInUseException | UnsupportedCommOperationException e) {
e.printStackTrace();
}
try {
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
/** These are the events we want to know about*/
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
serialPort.notifyOnRingIndicator(true);
} catch (TooManyListenersException e) {
e.printStackTrace();
}
//Register to home network of sim card
send("ATZ\r\n");
} else {
throw new NullPointerException("COM Port not found!!");
}
}
public void serialEvent(SerialPortEvent serialPortEvent) {
System.out.println("serialPortEvent.getEventType()"+serialPortEvent.getEventType());
switch (serialPortEvent.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
// System.out.println("Ringing");
if( serialPortEvent.getNewValue() )
{
System.out.println("Ring Indicator On");
}
else
{
System.out.println("Ring Indicator Off");
}
break;
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
case SerialPortEvent.DATA_AVAILABLE:
StringBuffer sb = new StringBuffer();
byte[] readBuffer = new byte[2048];
try {
while (inputStream.available() > 0)
{
int numBytes = inputStream.read(readBuffer);
sb.append(new String(readBuffer,0,numBytes));
System.out.println(numBytes);
System.out.println(sb);
}
System.out.println("Data Available");
if((sb.toString()).contains("RING")){
System.out.println("Enter Inside if RING Loop");
//play();
send("ATA\r\n");
//welcomeMessage();
}
if((sb.toString()).contains("CARRIER")){
hangup();
//Thread.sleep(1000);
closePort();
outCommand();
System.out.println("Enter Inside if NO CARRIER Loop");
}
//print response message
System.out.print(sb.toString());
} catch (IOException e) {
}
break;
}
}
public void outCommand(){
System.out.print(readBufferTrial);
}
public void ownershipChange(int type) {
switch (type) {
case CommPortOwnershipListener.PORT_UNOWNED:
System.out.println(portId.getName() + ": PORT_UNOWNED");
break;
case CommPortOwnershipListener.PORT_OWNED:
System.out.println(portId.getName() + ": PORT_OWNED");
break;
case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
System.out.println(portId.getName() + ": PORT_INUSED");
break;
}
}
public void closePort(){
serialPort.close();
}
public static void main(String args[]) {
GSMConnect gsm = new GSMConnect(comPort);
if (gsm.init()) {
try {
System.out.println("Initialization Success");
gsm.connect();
Thread.sleep(5000);
gsm.checkStatus();
Thread.sleep(5000);
// System.out.println("Before Auto Answer");
// gsm.send("ATS0=5");
// gsm.dial("87XXXXXSS");
// Thread.sleep(7500);
// System.out.println("After Auto Answer set");
// gsm.sendMessage("8XXXXXS56", "Trial Success Call me");
// gsm.sendMessage("80XXXXS56", "Trial Success Call me");
// gsm.sendMessage("8XXXXSXS6", "Trial Success Call me");
// Thread.sleep(5000);
// gsm.sendMessage("+919XXXXXXS3", "Third Msg");
// Thread.sleep(1000);
// gsm.dial("9XXXXS773");
// gsm.dial("871XXXXS5");
// Thread.sleep(1000);
// gsm.welcomeMessage();
// Thread.sleep(1000);
// gsm.welcomeMessage();// for turning on Echo ATE1&W
// Thread.sleep(20000);
// welcomeMessage();
// gsm.hangup();
// Thread.sleep(1000);
// gsm.closePort();
// gsm.outCommand();
// System.exit(1);
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Can't init this card");
}
}
}
Short of spending a good amount of time reproducing your environment I can give you two suggestions on how you might look into this.
a) Place a try-catch Throwable around your entire handler--often throwing exceptions can break event dispatchers
B) print out a debug statement when you enter and exit your event handler and ensure they are paired and that you get an exit after your last enter--a thread locking up will sometimes stop future events from being dispatched.
By the way you have an empty catch statement in one place--those scare the crap out of me because they often mask problems in ways that can waste days of your time. If you absolutely know you want to silently eat an exception there and you expect that exception to occur enough that it would pollute your logs to log it, please put a comment saying so.
I i am making a server/client but there seems to be a problem. I cannot seem to connect when i click the button.Please help.Not sure what i did wrong.Feel free to edit code to fix it then comment please.I have a connect button,and a send button. I think it has something to do with the highlighted code but it could be anything. I know this isnt very specific but basically heres the code and it doesnt work. I cant connect . please help!
Client
public class chat_client extends javax.swing.JFrame {
String username;
Socket sock;
BufferedReader reader;
PrintWriter writer;
ArrayList<String>userList = new ArrayList();
Boolean isConnected = false;
public chat_client() {
initComponents();
getContentPane().setBackground(Color.white);
this.setIconImage(new ImageIcon(getClass()
.getResource("dogeIcon.jpg")).getImage());
this.setLocationRelativeTo(null);
}
public class IncomingReader implements Runnable{
public void run(){
String stream;
String[] data;
String done = "Done", connect = "Connect",
disconnect = "Disconnect", chat = "Chat";
try {
while ((stream = reader.readLine()) != null){}
data = stream.split("^");
if (data[2].equals(chat)){
txtChat.append(data[0] + ":" + data[1] + "\n");
} else if (data[2].equals(connect)){
txtChat.removeAll();
userAdd(data[0]);
} else if (data[2].equals(disconnect)){
userRemove(data[0]);
} else if (data[2].equals(done)){
userList.setText("");
writeUsers();
}
} catch(Exception ex){
}
}
}
public void ListenThread(){
Thread IncomingReader = new Thread(new IncomingReader());
IncomingReader.start();
}
public void userAdd(String data){
userList.add(data);
}
public void userRemove(String data){
txtChat.append(data + " has disconnected \n");
}
public void writeUsers(){
String[] tempList = new String[(userList.size())];
userList.toArray(tempList);
for (String token:tempList){
userList.append(token + "\n");
}
}
public void sendDisconnect(){
String bye = (username + "^ ^Disconnected");
try{
writer.println(bye);
writer.flush();
} catch(Exception e){
txtChat.append("Could Not Send Disconnect Message \n");
}
}
public void Disconnect(){
try{
txtChat.append("Disconnected\n");
sock.close();
} catch(Exception ex){
txtChat.append("Failed to disconnect\n");
}
isConnected = false;
txtUser.setEditable(true);
userList.setText("");
}
(This is the highlighted part where i think the problem is)
***private void connectActionPerformed(java.awt.event.ActionEvent evt) {
if (isConnected == false){
username = txtUser.getText();
txtUser.setEditable(false);
try{
sock = new Socket("localhost", 1023);
InputStreamReader streamreader
= new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(streamreader);
writer = new PrintWriter(sock.getOutputStream());
writer.println(username + "^has connected.^Connect");
writer.flush();
isConnected = true;
} catch(Exception ex){
txtChat.append("Cannot Connect! Try Again\n");
txtUser.setEditable(true);
}
ListenThread();
} else if (isConnected == true){
txtChat.append("You is connected bra\n");
}
}***
(Ends here-the problem/highlighted part)
private void btn_SendActionPerformed(java.awt.event.ActionEvent evt) {
String nothing = "";
if ((txtMsg.getText()).equals(nothing)){
txtMsg.setText("");
txtMsg.requestFocus();
} else {
try{
writer.println(username + "^" + txtMsg.getText() + "^"
+ "Chat");
writer.flush();
} catch (Exception ex){
txtChat.append("Message was not sent\n");
}
txtMsg.setText("");
txtMsg.requestFocus();
}
A couple things:
You're getting a java.net.ConnectionException (see below) because the connection is being refused. This could be because the server you are trying to connect to is not running, the server is not accepting client connections, the server is not accessible by the client, or you are connecting to the wrong port number.
It is generally bad coding practice to catch Exception directly. You want to either catch the most specific exception that ranges across the variety of exceptions that can be thrown (in this case, IOException) or catch each possible one individually, which is the preferred method. Catch the most specific exceptions before the more general ones so that they are not masked by them. Furthermore it is a good idea to use the Throwable class's getMessage() method so that you can figure out the reason for the exception being thrown. For example:
} catch (java.net.ConnectException ex) {
System.err.println("ConnectException: " + ex.getMessage()); // May return "Connection refused", "Connection timed out", "Connection reset", etc.
} catch (java.rmi.UnknownHostException ex) {
System.err.println("UnknownHostException: " + ex.getMessage()); // Returns the name of the host you were attempting to connect to
} catch (...) {
// code here
} catch (java.io.IOException ex) {
System.err.println("IOException: " + ex.getMessage()); // May return a problem with the BufferedReader or InputStreamReader or PrintWriter
}
Of course, the statements in the catch clause can be modified to your liking.
I'm currently trying to implement the game of Nim using Java, I want to be able to have one player act as the server and another as the player.
I'm fairly new to Java networking and have only had experience using basic TCP/IP where the human client connects to a computer host.
The trouble I'm having is that I need to be able to differentiate between the different players whilst implementing the protocol for the game (The protocol being the logic for the game).
As it stands I can let one player (Client) interact with the Server. All that happens is the Client can play the game but there is no oppostion (The Server merely tracks the state of the game e.g. How many sticks left, valid input etc..).
How would I go about adding a second player to take the place of the host?
Edit:
The Client and Server code has been posted, it is the code I have used and I'm quite comfortable with, the question I am asking is would it be a suitable base to implement a multi-player game or would I need to do something completely different?
My Nim Protocol: (Untested)
public class NimLogic
{
private static final int WAITING = 0;
private static final int EVALUATING = 1;
private static final int ANOTHER = 2;
private int currentState = WAITING;
private int theInput = 0;
private int totalSticks = 10;
String processInput(String input) {
String theOutput = null;
try
{
theInput = Integer.parseInt(input);
}
catch (Exception e)
{
// Ignore conversion error
}
switch (currentState)
{
case WAITING:
theOutput = "Take how many sticks?";
currentState = EVALUATING;
break;
case EVALUATING:
if(theInput == 1 | theInput == 2 | theInput == 3)
{
if (theInput < totalSticks)
{
totalSticks -= theInput;
theOutput = "There are" + totalSticks + " left.";
}
else if (theInput > totalSticks)
{
theOutput = "Error: You cannot take more sticks than that are available";
currentState = EVALUATING;
}
}
if(totalSticks == 1)
{
theOutput = "Game Over! Play again? (Yes = 1, No = 0)...";
currentState = ANOTHER;
}
break;
case ANOTHER:
if (theInput == 1)
{
totalSticks = 10;
currentState = EVALUATING;
theOutput = "Take how many sticks?";
}
else
{
theOutput = "Bye.";
}
}
return theOutput;
}
}
Thanks for all the help!
Edit:
Client
public class Client
{
#SuppressWarnings("static-access")
public static void main(String machine[])
{
Socket kkSocket = null;
PrintStream os = null;
DataInputStream is = null;
try
{
kkSocket = new Socket(machine[0], 4444);
os = new PrintStream(kkSocket.getOutputStream());
is = new DataInputStream(kkSocket.getInputStream());
}
catch(UnknownHostException e)
{
System.err.println("Socket Connect failed on " + machine[0]);
}
catch (IOException e)
{
System.err.println("Streams failed on " + machine[0]);
}
if (kkSocket != null && os != null && is != null )
{
try
{
String fromServer, fromClient;
while((fromServer = is.readLine()) != null && !fromServer.equals("Bye."))
{
fromClient = JOptionPane.showInputDialog(fromServer);
os.println(fromClient);
}
JOptionPane.showMessageDialog(null, "Goodbye, keep smiling.");
os.close();
is.close();
kkSocket.close();
}
catch (UnknownHostException e)
{
System.err.println("Can't connect to " + machine[0] + e);
}
catch (IOException e)
{
e.printStackTrace();
System.err.println("I/O failed on " +machine[0]);
}
}
}
}
Server
public class Server
{
public static void main(String arg[])
{
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(4444);
}
catch (IOException e)
{
System.err.println("Can't listen on 4444 -> " + e);
System.exit(1);
}
Socket clientSocket = null;
try // allow the client to connect
{
clientSocket = serverSocket.accept();
}
catch (IOException e)
{
System.err.println("Failed accept on 4444 -> " + e);
System.exit(1);
}
try
{
DataInputStream is =
new DataInputStream(new BufferedInputStream
(clientSocket.getInputStream()));
PrintStream os =
new PrintStream(new BufferedOutputStream
(clientSocket.getOutputStream(), 1024), false);
GuessState kks = new GuessState();
String inputLine, outputLine;
outputLine = kks.processInput(null);
os.println(outputLine);
os.flush();
while((inputLine = is.readLine()) != null
&& !outputLine.equals("Bye."))
{
outputLine = kks.processInput(inputLine);
os.println(outputLine);
os.flush();
}
os.close();
is.close();
clientSocket.close();
serverSocket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
I'm not quite sure if I'm answering your question here, so apologies if I'm not. Also, it's been a little while since I did any Java networking code, so there might be a few wrinkles here which hopefully others can sort out.
The following is a bit of a brain dump of the changes I'd probably make, for better or worse...
Rework the networking code to accept multiple connections. Normally you'd do this by handing off the socket returned by ServerSocket.accept to a thread to process. If you were dealing with a lot of connections, you could do it using NIO instead, but that's probably too far to fast for now.
Separate the game state from the client conversation code. To keep things simple, embed the client conversation code in the thread object. The game state needs to be in an object that's shared between all the threads servicing the socket.
I'd recommend making the game state a proper 'domain object' rather than having it parsing strings etc. It should have operations like 'take(clientID, int)' rather than 'processInput'.
Consider using the observer pattern to distribute events from the domain object to the socket threads. Examples of events might be 'turnTaken' or 'gameComplete'.
Embed the notion of 'turns' into the game object, and have the server broadcast an event to the socket threads announcing whose turn it is.
Hope that gives you a starter for ten?
The server/client aspect should have no bearing on the communication of the two players. You should be able to spawn two instances of the Nim game, one that listen for an incoming connection on some port(Server), and one that connects to it (Client). Once the connection is established, you can pass Objects between the two instances over your connection that represent game information. Each instance of your Nim game is responsible for parsing that game data and running the Nim logic on it.
In essence, each instance of the game can run as a server or a client. Here's some code I wrote for Chess that should be applicable. Read through it. Elsewhere I instance a Server or Client and store it in a reference of type NetworkIdenitity.
private abstract class NetworkEntity
extends Thread {
ObjectOutputStream outputStream;
ObjectInputStream inputStream;
Socket connectionHandle;
Object messageToSend;
Object receivedMessage;
public NetworkEntity(final String name) {
super(name);
}
#Override
public abstract void run();
public void getStreams()
throws IOException {
this.outputStream = new ObjectOutputStream(this.connectionHandle.getOutputStream());
this.outputStream.flush();
this.inputStream = new ObjectInputStream(this.connectionHandle.getInputStream());
}
public void closeConnection() {
try {
if (this.outputStream != null) {
this.outputStream.close();
}
if (this.inputStream != null) {
this.inputStream.close();
}
if (this.connectionHandle != null) {
this.connectionHandle.close();
chatPanel.writeToDisplay("Connection closed with "
+ this.connectionHandle.getInetAddress().getHostName());
}
}
catch (final IOException e) {
JOptionPane.showMessageDialog(thisFrame, "Problems experienced when closing connection",
"Notification", JOptionPane.ERROR_MESSAGE);
}
}
public void processIncomingData()
throws IOException {
do {
try {
this.receivedMessage = this.inputStream.readObject();
}
catch (final ClassNotFoundException e) {
JOptionPane.showMessageDialog(thisFrame, "read() error: message from "
+ this.connectionHandle.getInetAddress().getHostName() + " not received", "Notification",
JOptionPane.ERROR_MESSAGE);
}
if (this.receivedMessage instanceof Move) {
final Move m = (Move) this.receivedMessage;
System.out.println(getName() + " got move" + m);
requestMove(Table.this.chessBoard, Table.this.currentPlayer, Table.this.currentOpponent, m, false);
repaint();
}
else if (this.receivedMessage instanceof Board) {
final Board b = (Board) this.receivedMessage;
System.out.println(getName() + " received this board:");
b.printCurrentBoardState();
// System.out.println("local copy looked like this: " );
// chessBoard.printCurrentBoardState();
// chessBoard.setGameBoard(b.getGameBoard());
// switchCurrentPlayer();
// chessBoard.updateBoardState(currentPlayer,
// currentOpponent);
repaint();
}
else if (this.receivedMessage instanceof String) {
chatPanel.writeToDisplay((String) this.receivedMessage);
}
} while (/* !message.equals("SERVER>>> TERMINATE") */true);
}
public void sendData(final Object obj_to_send) {
try {
this.outputStream.writeObject(obj_to_send);
this.outputStream.flush();
}
catch (final IOException e) {
}
}
}
private final class Client
extends NetworkEntity {
private final String hostName;
private final int serverPort;
public Client(final String host, final int port) {
super("CLIENT");
this.hostName = host;
this.serverPort = port;
}
#Override
public void run() {
try {
connectToServer();
getStreams();
processIncomingData();
}
catch (final EOFException eof) {
}
catch (final IOException ioe) {
}
catch (final NullPointerException npe) {
}
finally {
closeConnection();
}
}
private void connectToServer()
throws IOException {
try {
this.connectionHandle = new Socket(InetAddress.getByName(this.hostName), this.serverPort);
connectionEstablished = true;
chatPanel.writeToDisplay("Successfully connected to "
+ this.connectionHandle.getInetAddress().getHostName());
}
catch (final IOException e) {
chatPanel.writeToDisplay("Failed to connect to: " + this.hostName);
}
}
}
private final class Server
extends NetworkEntity {
private ServerSocket server;
private final int listenPort;
public Server(final int listen_port) {
super("SERVER");
this.listenPort = listen_port;
}
#Override
public void run() {
try {
this.server = new ServerSocket(this.listenPort, 1);
chatPanel.writeToDisplay("Listening on port " + this.listenPort);
try {
waitForConnection();
getStreams();
processIncomingData();
}
catch (final EOFException eof) {
// System.out.println(getName() + "exception: " +eof);
// eof.printStackTrace();
}
catch (final IOException ioe) {
// System.out.println(getName() + "exception: " +ioe);
// ioe.printStackTrace();
}
finally {
closeConnection();
}
}
catch (final IOException e) {
JOptionPane.showMessageDialog(thisFrame, "Network Error: " + e, "Notification",
JOptionPane.ERROR_MESSAGE);
}
}
private void waitForConnection()
throws IOException {
this.connectionHandle = this.server.accept();
connectionEstablished = true;
chatPanel.writeToDisplay("Connection received from:" + this.connectionHandle.getInetAddress().getHostName());
}
#Override
public void closeConnection() {
super.closeConnection();
try {
this.server.close();
}
catch (final IOException e) {
chatPanel.writeToDisplay(getName() + "failed to disconnect from the network");
}
}