I have a problem with multithreading. I don't know why, but threads run in sequence.
There is a client-server application. I need to run several parallel threads for message exchange. The whole classes are too big, so I will show main parts.
Code of Client(This code runs every time when I push the button):
public ArrayList<Action> call() {
Thread myThready = new Thread(new Runnable()
{
public void run()
{
BufferedReader in;
PrintWriter out;
try{
Socket fromserver = new Socket(ip, PortID);
in = new BufferedReader(new InputStreamReader(fromserver.getInputStream()));
out = new PrintWriter(fromserver.getOutputStream(),true);
writeLog(query, ID, 0);
out.println(query+"ID"+ID);
String fserver = in.readLine();
writeLog(fserver, ID, 1);
out.println("exit");
out.close();
in.close();
fromserver.close();
}
catch (IOException io){
return;
}
}
});
myThready.start();
}
Code of Server:
public void run(){
flag=true;
System.out.println("Welcome to Server side!");
createLog();
ExecutorService service = Executors.newCachedThreadPool();
ServerSocket servers = null;
int n=4600;
try{
servers = new ServerSocket(n);
} catch( Exception e){
}
Socket fromclient = null;
while(true){
try {
System.out.print("Waiting for a client...");
fromclient = servers.accept();
System.out.println("Client connected.");
Callable<ArrayList<Action>> callable = new HandleThread(fromclient);
Future<ArrayList<Action>> future = service.submit(callable);
list.addAll(future.get());
} catch (Exception e) {
System.out.println("Can't accept.");
System.exit(-1);
}
}
}
This code does "accept()" and then creates new thread for some calculations.
Code of HandleThread:
public ArrayList<Action> call() {
BufferedReader in = null;
PrintWriter out= null;
try {
in = new BufferedReader(new
InputStreamReader(fromclient.getInputStream()));
out = new PrintWriter(fromclient.getOutputStream(),true);
String input,output;
System.out.println("Wait for messages.");
while ((input = in.readLine()) != null) {
//close filewriter thread if input==exit
if(input.equalsIgnoreCase("exit")){
break;
}
System.out.println(input);
String[] arr = input.split("ID");
System.out.println("+"+arr[0]);
ID = Integer.parseInt(arr[1]);
writeLog(arr[0], ID, 0);
process(arr[0], ID);
out.println(arr[0]);
writeLog(arr[0], ID, 1);
}
out.close();
in.close();
fromclient.close();
} catch(IOException e){
return null;
}
return list;
}
I don't know why this doesn't work. I have logs and I see that one thread runs only after another one. Not at the same time!
Please, help me!
Future#get() is a blocking call.
list.addAll(future.get());
The calling thread will wait until the task is done. As such, your server thread which calls accept() waits for each task to finish before it gets to the next one.
Related
I'm using a method called registerDevice() in my android app
code to send and receive specific data which contains multiple lines. But I keep getting this error:
W/System.err: java.net.SocketException: Connection reset
public void registerDevice(){
final Handler handler = new Handler();
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
Socket s = new Socket(gateway, 1234);
OutputStream out = s.getOutputStream();
PrintWriter output = new PrintWriter(out);
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
output.println("hello world\r\n");
output.flush();
StringBuffer stringBuffer = new StringBuffer("");
String line = null;
while ((line = input.readLine()) != null) {
stringBuffer.append(line);
}
final String st = line.substring(5);
handler.post(new Runnable() {
#Override
public void run() {
if (st.trim().length() != 0)
Toast.makeText(getApplicationContext(),st,Toast.LENGTH_LONG).show();
}
});
output.close();
out.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
UPDATE: I changed the code to this:
Socket s = new Socket(gateway, 1234);
OutputStream out = s.getOutputStream();
PrintWriter output = new PrintWriter(out);
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
output.println("hello world\r\n");
output.flush();
final String st = input.readLine();
handler.post(new Runnable() {
#Override
public void run() {
if (st.trim().length() != 0)
Toast.makeText(getApplicationContext(),"st",Toast.LENGTH_LONG).show();
}
});
output.close();
out.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I'm Still getting exceptions on the "final String st = input.readLine();" line. I am supposed to get a MAC address from the server and then the server closes the connection.I checked the server and there is nothing wrong with it, it closes the connection AFTER it sends me the MAC.
Guys I found the problem, it was the packet I was sending, I just changed outout.println() to output.write(), so now the server recognized my command and sent the data I needed which led to my input stream not being empty and avoiding exceptions.
I have a program which is to be a chat program between a client and server. I set the sockets up depending on which button was clicked like this:
public void actionPerformed(ActionEvent e)
{
Object o = e.getSource();
if(o==startServer)
{
startServer.enable(false);
try{
listenSocket = new ServerSocket(port);
Socket client = listenSocket.accept();
InputStreamReader is = new InputStreamReader(client.getInputStream());
BufferedReader buffRdr = new BufferedReader(is);
PrintWriter printWrt = new PrintWriter(client.getOutputStream(),true);
service = 1;
sendButton.enable(true);
disconnectButton.enable(true);
sendText.enable(true);
more = true;
}catch(IOException ie){
ie.printStackTrace();
}
}
if(o==connectButton)
{
try{
startServer.enable(false);
connectButton.enable(false);
Socket server = new Socket(host,port);
InputStreamReader is = new InputStreamReader(server.getInputStream());
BufferedReader buffRdr = new BufferedReader(is);
PrintWriter printWrt = new PrintWriter(server.getOutputStream(),true);
service = 2;
sendButton.enable(true);
disconnectButton.enable(true);
sendText.enable(true);
more = true;
}catch(IOException ie){
ie.printStackTrace();
}
}
I run two instances of the program and everything seems to connect but im not sure how the program knows to get the text from the sendText textBox i have set up. Here is how i have my run set up but it never gets to the System.out.println("Service Changed") or where i append "Listening to socket" after the program waits for the service to change from 0.
while(more)
{
statusArea.append("Chat Running");
String line;
try{
System.out.println(service);
while(service==0 && more);
System.out.println("Service Changed");
if(buffRdr!=null)
{
statusArea.append("Listening to socket");
while(more && (line=buffRdr.readLine())!=null)
{
chatArea.append(line);
}
}
}catch(IOException e)
{
}
}
Any help on this would be appreciated, im rather new at programming in java
I am very new to sockets and was hoping someone could help me. I had something working but it was not sending information very quickly so i have refactored and now cannot get back to anything which works. The issue seems to be that only the first message that is published is read and then the receiver sits on client = listener.accept(); even though im pretty sure the sender is still sending messages
Can anyone see what i might be doing wrong here please?
Thanks
public class Sender {
Socket server = null;
DataInputStream inp = null;
PrintStream outp = null;
public Sender(){
server = new Socket("127.0.0.1" , 3456);
outp = new PrintStream(server.getOutputStream());
}
private void connectAndSendToServer(String message) {
outp = new PrintStream(server.getOutputStream());
outp.print(message + "\n");
outp.flush();
}
}
Receiver class
public class Receive{
public String receiveMessage(int port) {
String message= null;
ServerSocket listener = null;
Socket client = null;
try{
listener = new ServerSocket(port);
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
return br.readLine();
}
...
finally{
try {
if(client!=null && listener!=null){
client.close();
listener.close();
}
}
catch (IOException e) {
}
}
return message;
}
}
This because a ServerSocket is used as an entry point for a normal Socket. accept() is a blocking operation that is usually done on a different thread compared to the one that receives/sends data to normal Socket. It sits there and waits for a new connection to spawn a new Socket which is then used for data.
This means that while receiving messages you should call just readLine() to read from the specific Socket. Having an accept inside the receiveMessage is wrong just because it's a different operation and it's even blocking.
Socket socket = serverSocket.accept();
ClientThread thread = new ClientThread(socket);
class ClientThread extends Thread {
Socket socket;
public void run() {
while (!closed) {
String line = reader.readLine();
...
}
}
You don't need to have a thread for every client though, but you need at least two for sure if you want to make your server accept a number of connections greater than 1.
You are not using ServerSocket correctly. You shouldn't create a new instance for every message but use it as a data member maybe and run an infinite loop to get a new client socket connection. Because you create it locally, the socket is closed since the object is no longer used and referenced (and so GC'ed), when you return from the method.
Something like (< condition met > is pseudo-code defines your condition to accept new connections):
while(< condition met >) {
try {
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String str = br.readLine();
//do something with str
} finally {
//close client socket
}
}
Better approach will be to handle client socket in a different thread so the main thread is back to accept while you can do anything with the client socket in parallel.
Try this basic Chatting Server written by me. This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
// ///----------------------------------------Instance Variable Fields
ServerSocket ss = null;
Socket incoming = null;
// ///----------------------------------------Instance Variable Fields
// ///---------------------------------------- static Variable Fields
public static ArrayList<Socket> socList = new ArrayList<Socket>();
// ///---------------------------------------- static Variable Fields
public void go() {
try {
ss = new ServerSocket(25005);
while (true) {
incoming = ss.accept();
socList.add(incoming);
System.out.println("Incoming: " + incoming);
new Thread(new ClientHandleKaro(incoming)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandleKaro implements Runnable {
InputStream is = null;
OutputStream os = null;
InputStreamReader isr = null;
BufferedReader br = null;
PrintWriter pw = null;
boolean isDone = false;
Socket sInThread = null;
public ClientHandleKaro(Socket sxxx) {
this.sInThread = sxxx;
}
#Override
public void run() {
if (sInThread.isConnected()) {
System.out.println("Welcamu Clienta");
System.out.println(socList);
}
try {
is = sInThread.getInputStream();
System.out.println("IS: " + is);
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
os = sInThread.getOutputStream();
pw = new PrintWriter(os, true);
String s = new String();
while ((!isDone) && (s = br.readLine()) != null) {
String[] asx = s.split("-");
System.out.println("On Console: " + s);
// pw.println(s);
Thread tx = new Thread(new ReplyKaroToClient(s,
this.sInThread));
tx.start();
if (asx[1].trim().equalsIgnoreCase("BYE")) {
System.out.println("I am inside Bye");
isDone = true;
}
}
} catch (IOException e) {
System.out.println("Thanks for Chatting.....");
} finally {
try {
Thread tiku = new Thread(new ByeByeKarDo(sInThread));
tiku.start();
try {
tiku.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Accha to hum Chalte hain !!!");
System.out.println(socList);
br.close();
pw.close();
sInThread.close();
} catch (IOException e) {
}
}
}
}
class ReplyKaroToClient implements Runnable {
public String mString;
public Socket mSocket;
public ReplyKaroToClient(String s, Socket sIn) {
this.mString = s;
this.mSocket = sIn;
}
#Override
public void run() {
for (Socket sRaW : socList) {
if (mSocket.equals(sRaW)) {
System.out.println("Mai same hun");
continue;
} else {
try {
new PrintWriter(sRaW.getOutputStream(), true)
.println(mString);
} catch (IOException e) {
System.out.println("Its in Catch");
}
}
}
}
}
class ByeByeKarDo implements Runnable {
Socket inCom;
public ByeByeKarDo(Socket si) {
this.inCom = si;
}
#Override
public void run() {
try {
new PrintWriter(inCom.getOutputStream(), true)
.println("You have Logged Out of Server... Thanks for your Visit");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().go();
}
}
I have a relatively simple program where I try establish Client Server connection and at the same time I use threads in the client side to allow for multiple connections.
I run the server and then the server invokes the client constructor and passes the port connection to the client and the thread is started on the client side.
The problem I have is that when I run the server side it doesn't want to go beyond the constructor call. It seems to get stuck at the constructor.
Sorry all this sounds a bit confusing
Any thoughts perhaps
this is the server side
ServerMultipleThreads()
{
System.out.println("Starting the server first...");
try
{
ServerSoc = new ServerSocket(7777);
listening = true;
}
catch(Exception e)
{
System.out.println(e.toString());
System.exit(1);
}
System.out.println("The server has started running");
while(listening)
{
try
{
//creating the client socket and starting the new client session
new ClientSession(ServerSoc.accept());
System.out.println("The clientSession was called");
in = new DataInputStream(clientSocket.getInputStream());
BufferedReader is = new BufferedReader(new InputStreamReader(in));
os = new PrintStream(clientSocket.getOutputStream());
while(true)
{
line = is.readLine();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("myFile,txt")), true);
out.println(line);
}
}
catch(IOException ioe)
{
System.out.println(ioe.toString());
}
}
}
and this is on client side
ClientSession(Socket s)
{
clientSocket = s;
try
{
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out.println("Welcome");
}
catch(IOException exe)
{
System.out.println(exe.toString());
}
//starting the thread
while(runner == null)
{
runner = new Thread(this);
runner.start();
}
}
public void run()
{
while(runner == Thread.currentThread())
{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String stdIn;
try
{
while((stdIn = buf.readLine()) != null)
{
out.println(stdIn);
}
}
catch(IOException exe)
{
exe.toString();
}
try
{
Thread.sleep(10);
}
catch(InterruptedException e){}
}
Kind regards
Arian
That is because ServerSocket.accept() blocks until it receives a client request.
You need to have a client calling the server, something like this:
Socket socket = new Socket(host, port);
InputStream in = socket.getInputStream();
// write some data...
I am trying to write a small program, that opens a server, creates a client that connects to this server and receives a message from it.
This is the Code so far
public static void main(String[] args) {
final ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(12345);
Thread t = new Thread(){
public void run(){
try {
Socket server = serverSocket.accept();
PrintWriter writer = new PrintWriter(server.getOutputStream(), true);
writer.write("Hello World");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t.start();
Socket client = new Socket("localhost", 12345);
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
String message = reader.readLine();
System.out.println("Received " + message);
} catch (IOException e1) {
e1.printStackTrace();
}
}
If i run program it keeps waiting in readLine() - so obviously the client does not receive the message from the server.
Has anyone got an idea why this isn' working?
Your reading thread is waiting for a newline in the data stream. Just change the server to use:
writer.write("Hello World\r\n");
and you'll get the result you were expecting. Alternatively, you can just close the server socket, and then readLine will return when it reaches the end of the data stream.
You should put the readline in a loop as follows:
public static void main(String[] args) {
final ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(12345);
Thread t = new Thread() {
public void run() {
try {
Socket server = serverSocket.accept();
PrintWriter writer = new PrintWriter(server.getOutputStream(), true);
writer.write("Hello World");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t.start();
Socket client = new Socket("localhost", 12345);
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
// Check this --------------------------------------------------->
String message = null;
while ((message = in.readLine()) != null) {
System.out.println("Received " + message);
break; //This break will exit the loop when the first message is sent by the server
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
You can read this documentation for further explanation: http://download.oracle.com/javase/tutorial/networking/sockets/