java socket freeze after a while (using threadpool) - java

I'm writing a program where I need to send multiple http requests to a lot of domains using socket. I used thread pool and socket when I start the program. It starts fast then it slows down, finally it freezes (terminal is still running).
public class HttpRequest implements Runnable{
private String url;
private Socket s;
public boolean scanned;
private String extension;
public HttpRequest(String url,String extension) throws UnknownHostException, IOException {
this.url=url;
this.extension=extension;
s=new Socket(url,80);
//
//s.setSoTimeout(600000);
}
public void run() {
String data="";
String html="";
try {
PrintWriter p=new PrintWriter(s.getOutputStream(),true);
p.println("GET /"+extension+" HTTP/1.1");
p.println("Host:"+url);
p.println("");
BufferedReader r= new BufferedReader(new InputStreamReader(s.getInputStream()));
if(r.readLine().indexOf("200 OK")!=-1) {
while ((data=r.readLine())!=null) {
html+=data;
Document d =Jsoup.parse(html);
Element form=d.select("form").first();
String value=form.attr("enctype");
if(value=="multipart/form-data") {
System.out.println("value is :"+value);
System.out.println(" found"+this.url+"/"+extension);
}
System.out.println(d.title() + this.url+"/"+extension+" "+Thread.currentThread().getName());
}}
else {
System.out.println("failed => "+this.url +"/"+ extension +" "+Thread.currentThread().getName());
}
s.close();
//}
}catch(Exception e) {
}
}
}
here is the main
I have a domain array which contain urls which I will make a request to
ExecutorService exe= Executors.newFixedThreadPool(40);
for (int i =0 ; i <= domains.length-1; i++) {
h=new handeler(domains[i]);
exe.execute(h);
}

Related

Multi threating Java Server

I am writing simple Java Server which connecting only 5 users and run simply game.
My problem is communicate with clients, because the Game object is in Main Thread and every single subthread get information about specific player move (1-5 id). I don't know how to send this information to Main Thread and update game status.
Is my code correct, there aren't exists any big mistakes (this is my first project with multitasking), and what i supposed to do to communicate with Main Thread
Player.java
package Model;
import java.io.*;
import java.net.Socket;
public class Player extends Thread{
private long id;
private Socket clientSocket;
private InputStream clientInput;
private BufferedReader clientIn;
private DataOutputStream clientOut;
private String nickname;
private boolean isReady;
public Player(long id, Socket clientSocket) throws IOException {
this.id = id;
this.clientSocket = clientSocket;
this.clientInput = this.clientSocket.getInputStream();
this.clientIn = new BufferedReader(new InputStreamReader(this.clientInput));
this.clientOut = new DataOutputStream(this.clientSocket.getOutputStream());
this.isReady = false;
clientOut.writeBytes("POLACZONO\n");
clientOut.flush();
}
public void run() {
boolean isCorrect = false;
try {
while(!isCorrect) {
String login = this.clientIn.readLine();
if (!login.equals("") && login.startsWith("LOGIN") && login.length() > 6) {
this.clientOut.writeBytes("OK\n");
this.clientOut.flush();
setNickname(login.substring(login.indexOf(" ") + 1));
isCorrect = true;
this.isReady = true;
} else if (!login.equals("") && (!login.startsWith("LOGIN") || login.length() <= 6)) {
this.clientOut.writeBytes("ERROR\n");
this.clientOut.flush();
}
}
while (true) {
//DATA FROM CLIENT
}
//this.clientOut.writeBytes("START " + this.id + " " + startPlayer + "\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
this.clientSocket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Main Thread
public void startServer(ServerSocket serverSocket) throws IOException {
playerList = Collections.synchronizedList(new ArrayList<Player>());
int remaining = 1;
while (true) {
if(playerList.size() < 5) {
while (playerList.size() < 5) {
Socket connectionSocket = serverSocket.accept();
playerList.add(new Player(remaining, connectionSocket));
playerList.get(playerList.size() - 1).start();
remaining++;
}
}
final int startPlayer;
if(!playerList.stream().noneMatch(x -> x.isReady())) {
startPlayer = new Random().nextInt((5 - 1) + 1) + 1;
for (Player player : playerList) {
player.getClientOut().writeBytes("START " + player.getId() + " " + startPlayer + "\n");
}
//GAME START
}
}
}
Ok it means you used one thread per user for read data and just one thread to send data to users !
In main thread you can use a LinkedBlockingQueue and pass this queue to reader threads ! Each time a packet received you can put it to the queue and take it in main thread !
Soyou must write this in your reader thread :
queue.put(data);
And this in main thread :
data = queue.take();
This queue is thread safe , so it means multi thread can put and take data !
The take method will block thread until a data put to the queue.

JAVA: Serialization works good on Local Machine but when I do this in LAN it does not output correct

I want to send an object having OS Name to a server. This OS Name output should be of PC sending object but it displays OS Name of PC running server..
Here is my code :
//Client : it can send data i.e. object to server
class Client
{
private Socket socket = null;
private ObjectOutputStream outputStream = null;
public Client(String con){
System.out.println("conn value: "+con);
java.util.Timer t = new java.util.Timer();
try{
socket = new Socket(con, 27051);
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
outputStream = new ObjectOutputStream(socket.getOutputStream());
SI sysinfo=new SI();
outputStream.writeObject(sysinfo);
System.out.println("Sent Data: "+sysinfo.otherInfo());
} catch (Exception se) {
t.cancel();
}
}
}, 0, 1);
}
catch(Exception em)
{
}
}
}
//Server class: should receive data from client
class Server extends SwingWorker<Void,Void>{
Socket csocket=null;
protected Void doInBackground() throws Exception {
final ServerSocket ssock = new ServerSocket(27051);
System.out.println("Server Listening..!!");
while (true) {
try{
Socket sock = ssock.accept();
new Thread(new Server(sock)).start();
}
catch(Exception e){
System.out.println("unabke to create socket");
}
}
}
Server() throws Exception{
doInBackground();
}
Server(Socket csocket) {
this.csocket=csocket;
Thread t1=new Thread(r1);
t1.start();
}
Runnable r1=new Runnable()
{
public void run() {
try {
System.out.println("Run initated");
while(true)
{
if(csocket.isClosed())
{
break;
}
else{
System.out.println(csocket);
ObjectInputStream inStream = new
ObjectInputStream(csocket.getInputStream());
SI sysinfo= (SI) inStream.readObject();
System.out.println("Received: "+sysinfo.otherInfo());
System.out.println(ObjectStreamClass.lookup(sysinfo.getClass()).getSerialVersion
UID());
}
}
}
catch (Exception e) {
System.out.println("Exception"+ e.getMessage());
}
}
};
}
//class undergoing serialization
public class SI implements Serializable
{
private static final long serialVersionUID = 1L;
String otherInfo()
{
OperatingSystemMXBean bean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
.getOperatingSystemMXBean();
String os_name=bean.getName();
return os_name;
}
}
//class A: It has main function and it executes first and user decides whether he/she want to be in server mode or in client mode. As user cannot be in 2 modes simultaneously..
class A
{
public static void main(String[] args) throws Exception
{
System.out.println("Enter 0 for Server 1 for Client Mode");
Scanner s=new Scanner(System.in);
int i=s.nextInt();
if(i==0)
{
Server ser=new Server();
ser.execute();
}
else if(i==1)
{
System.out.println("Enter IP");
String conn=s.next();
Client c=new Client(conn);
}
else
System.out.println("Invalid Selection exit..");
}
}
As I wrote in my comment you must transfer the data, not the function. Some sample code below...
First, change your SI class as follows:
public class SI implements Serializable {
private static final long serialVersionUID = 1L;
private String osName;
public void setOsName(String osName) { this.osName = osName; }
public void getOsName() { return this.osName; }
}
Second, modify your client to first determine the OS and the build the SI object...
...
OperatingSystemMXBean bean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
.getOperatingSystemMXBean();
String osName=bean.getName();
SI sysinfo = new SI();
sysinfo.setOsName(osName);
...
outputStream.writeObject(sysinfo);
...
Third, modify your server accordingly.

Update data in Java in multiple processes active on the same time

I'm creating a token ring with sensors where every sensor is a process apart. When i start a sensor it communicates with the gateway and gets the list of the actual sensors already on the system .
The problem is that every time i start a new process i want every already existing sensor to get the updated list, so to understand that other sensors have been added and the list is no longer the one they had but a new updated one.(So lets say the processes must always have the same list). I use a server which i call serverSocket which listens for messages. I can make it possible for the server to understand that the list has been changed but what i cant do is how to change the value of the sensorList found on my SensorClient class, to be updated? In the code bellow i show what i'm doing but the sensorList keeps being the old one,not being updated :/ Can anyone please help me? Thank you :)
SensorClient where i start a new process sensor
public class SensorClient {
public static void main(String[] args) throws Exception {
Sensor sensor = new Sensor(type,identificator,portnumber,ipnumber,gatewayAddr,timestamp);
Gson gson = new Gson();
String message = gson.toJson(sensor);
Client c = Client.create();
WebResource r = c.resource("http://localhost:9999/gateway/");
ClientResponse response = r.path("sensors/add").type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, message);
if (response.getStatus() == 200) {
repeat = false;
Type collectionType = new TypeToken<ArrayList<Sensor>>(){}.getType();
ArrayList<Sensor> sensorList = gson.fromJson(response.getEntity(String.class), collectionType);
System.out.println("Starting the sensor ...");
System.out.println("Push exit when you want to delete the sensor!");
int position = 0;
for(int i = 0; i< sensorList.size();i++){ if(sensorList.get(i).getIdentificator().equalsIgnoreCase(sensor.getIdentificator()) ) position = i;
}
sensors.Sensor.simulation(type, identificator);// special thread for sensors simulations
createSensor.getInstance().setPrevNextWhenAdd(position,sensorList);
serverSocket serverSocket = new serverSocket(portnumber,sensorList,position,sensorList.get(position).getNext());
serverSocket.start();
StopSensor stopSensor = new StopSensor(identificator,portnumber,position,sensorList);
stopSensor.start();
oneSensor s = new oneSensor(portnumber,sensorList);
s.start();
} else {
repeat = true;
count +=1;
System.out.println("Error. Wrong data! ");
}
}
while (repeat );
}
}
}
The serverSocket thread
public class serverSocket extends Thread {
public int port,nextPort;
ArrayList<gateway.Sensor> sensorList;
public static int position;
public serverSocket(int port, ArrayList<gateway.Sensor> sensorList,int position,int nextPort) {
this.port = port;
this.nextPort=nextPort;
this.sensorList= sensorList;
this.position=position;}
public void run() {
ServerSocket welcomeSocket;
Socket connectionSocket;
try {
welcomeSocket = new ServerSocket(port);
while (true) {
connectionSocket = welcomeSocket.accept();
receivedMessages thread = new receivedMessages(connectionSocket,sensorList,position,nextPort);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
System.err.println("Error!!!!!!!!!");
}
}
}
The receivedMessages thread
public class receivedMessages extends Thread {
private BufferedReader inFromClient;
private Socket connectionSocket;
ArrayList<gateway.Sensor> sensorList;
int position,nextPort;
public receivedMessages(Socket socket, ArrayList<gateway.Sensor> sensorList,int position,int nextPort){
connectionSocket = socket;
this.sensorList=sensorList;
this.position=position;
this.nextPort=nextPort;
try {
inFromClient = new BufferedReader( new InputStreamReader(connectionSocket.getInputStream()));
} catch (IOException e) { e.printStackTrace(); }
}
#Override
public void run() {
try {
String message = (inFromClient.readLine().toString());
if (message.startsWith("Next") || message.startsWith("Previous")) {
System.out.println(message);
} else if (message.startsWith("The")) {
System.out.println(message); createSensor.getInstance().setPrevNextWhenDelete(position, sensorList);
} else {// i receive the message that the list has changed
System.out.println(message);
sensorList = createSensor.getInstance().getSensorList();
System.out.println("Updated " + sensorList);}
This class has methods used by gateway to register a sensor when it makes the request
public class createSensor {
private static createSensor instance = null;
private ArrayList<Sensor> sensor = new ArrayList<>();
public int position, prevPosition, nextPosition, prevPort, nextPort;
private createSensor() { }
public static synchronized createSensor getInstance() {
if (instance == null) {
instance = new createSensor();
}
return instance;
}
public synchronized ArrayList insertSensor(String type, String identificator, int port, String id, String gatwayAddr, long timestamp) throws IOException {
sensor.add(new Sensor(type, identificator, port, id, gatwayAddr, timestamp));
return new ArrayList<>(sensor); //
}
}
public synchronized boolean hasMeasurements() {
while (InnerBuffer.getInstance().emptyInnerBuffer())
return false;
return true;
}
public synchronized void setPrevNextWhenDelete(int position,ArrayList<Sensor> sensorList) throws IOException {
//code
}
public synchronized ArrayList<Sensor> getSensorList() {
return new ArrayList<>(sensor);
}
public synchronized int size() {
return sensor.size();
}
public synchronized String returnRecentMeasurement (String id){
String recentMeasurement=null;
for (Sensor sensori : sensor) {
if (sensori.getIdentificator().equalsIgnoreCase(id))
recentMeasurement= InnerBuffer.getInstance().returnRecentMeasurements(id);
else
recentMeasurement = null;}
return recentMeasurement;
}
public synchronized void setPrevNextWhenAdd() throws IOException { //some other code where int position, prevPosition, nextPosition, prevPort, nextPort get their values. }}

Syncronizing a multithreaded server

Hello everyone i have created a multi threaded chat server that looks like this:
public class Main {
public static ServerSocket server;
public static Socket connection;
public static int backLog = 100;
public static int numberOfConnected;
public static boolean connected = false;
public final static int potNumber = 6080;
public static PrintWriter pw;
public static Scanner input;
public static int i = 0;
public static void main(String[] args) {
startServer();
}
public static void startServer(){
try {
server = new ServerSocket(potNumber, backLog);
waitingForConnection();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void waitingForConnection() {
connected = false;
i++;
while (!connected) {
try {
if (connected) {
}
connection = server.accept();
Server s = new Server(connection, pw = new PrintWriter(connection.getOutputStream()), input = new Scanner(connection.getInputStream()));
s.start();
numberOfConnected++;
waitingForConnection();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The idea is that this is suppose to be a chat server so when one connects to the server it starts the following thread:
threads
public void run(){
while (connection.isConnected()) {
if (input.hasNext()) {
String fullMessage = input.nextLine();
if (fullMessage.equalsIgnoreCase("Connect")) {
connectHim();
}else {
chatMessage(fullMessage);
}
}
}
}
private void chatMessage(String fullMessage) {
String name = fullMessage.substring(0, fullMessage.indexOf(" "));
String message = fullMessage.substring(fullMessage.indexOf(" "), fullMessage.length());
pw.println(name+": "+message);
pw.flush();
}
private void connectHim() {
String name = input.nextLine();
pw.println(0);
pw.flush();
pw.println(1);
pw.flush();
pw.println();
pw.flush();
pw.println(name);
pw.flush();
}
So my problem is the following:
if the user that is bound to thread 1 (this is an example) and the user bound to thread 2 sends a message to the server how will i send that message to the user bound on thread 1?
One of options is to use Hashtable or HashMap (just call Collections.synchronizedMap(myMap) in case of Map usage). When you start new Thread, give him unique name (for example user nick name ) and put it to your collection where key - Thread name, and value - Thread as Object.
if the user that is bound to thread 1 (this is an example) and the user bound to thread 2 sends a message to the server how will i send that message to the user bound on thread 1?
For example you have user1, user2, user3. Now you build 3 Threads and put them to HashMap, like:
Map<String, Thread> threadMap = new HashMap<String,Thread>();
threadMap = Collections.synchronizedMap(threadMap);
YourThread th1 = new YourThread();
threadMap.put("user1", th);
YourThread th2 = new YourThread();
threadMap.put("user2", th);
YourThread th3 = new YourThread();
threadMap.put("user3", th);
....
Set<String> userSet = threadMap.keySet();
Iterator<String> it = userSet.iterator();
Thread currThread = null;
while(it.hasNext()){
String key = it.next();
currThread = threadMap.get(key);
// do something with currThread
}

Facing issue in java MultiThreading

Im facing one problem in streaming data capture for reading the broadcast data during multithreading, pls help or suggest,
Actually there is one class which is reading data from one of the udp socket. Another class accepts the tcp connection from every client request, creates a thread for every client and request the same udp class for data. The thing is working with 1st thread which gets created. But when i request with another client from another pc/ip the packets get losted to the 2nd client/thread
I have made a workaround by creating a list where im storing the Threads outputstream object
and looping it to send the data to all the client. But this is just temporary as it ll delay the packets if clients/connections gets increased.
code for reading UDP Data
public class EventNotifier
{
private InterestingEvent ie;
public DatagramSocket clientSocket;
public String[] split_str;
byte[] receiveData;
HashMap<String, String> secMap = new HashMap<String, String>();
public EventNotifier(InterestingEvent event)
{
ie = event;
clientSocket = new DatagramSocket(9050);
receiveData = new byte[500];
}
public String getDataFeed(String client_id)
{
try
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String s = new String(receivePacket.getData());
String split_str = s.split(",");
if(secMap.containsValue(split_str[0]))
return s;
else
return "";
} catch(Exception e3) {}
}
}// end of eventNotifier class
code for multithreading handling client requests
public class multiServer
{
static protected List<PrintWriter> writers = new ArrayList<PrintWriter>();
static String client_id = "";
public static void main(String[] args)
{
try
{
ServerSocket servsock = new ServerSocket(8858);
Socket incoming;
while(true)
{
incoming = servsock.accept();
multiServerThread connection = new multiServerThread(incoming);
Thread t1 = new Thread(connection);
t1.start();
}
}
catch(IOException e)
{
System.out.println("couldnt make socket");
}
}
}
class multiServerThread extends Thread implements InterestingEvent
{
Socket incoming;
PrintWriter out=null;
PrintWriter broad=null;
BufferedReader in = null;
String cliString=null;
private EventNotifier en;
int id;
public static String udp_data;
public void interestingEvent(String str1)
{
this.udp_data = str1;
}
public String getUdpData()
{
String _udp_data = this.udp_data;
return _udp_data;
}
multiServerThread(Socket incoming)
{
this.incoming=incoming;
en = new EventNotifier(this);
}
public void run()
{
try
{
out = new PrintWriter(incoming.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
cliString = in.readLine();
multiServer.writers.add(out);
while(true)
{
try
{
udp_data = en.getDataFeed(cliString);
if(udp_data!=null && udp_data.length()>0)
{
//workaround for serving the data to all cleints who are connected
for (int i=0; i<multiServer.writers.size();i++)
{
broad=multiServer.writers.get(i);
broad.println(udp_data.trim());
}
//else will directly write to the outputstream object for every thread which is connected
// out.println(udp_data.trim());
}
}
catch (Exception e)
{
System.out.println("exception "+e);
}
Thread.sleep(1);
}
} catch(IOException e)
{
System.out.print("IO Exception :: "+ e);
}
catch(InterruptedException e)
{
System.out.print("exception "+ e);
}
}
}
You need mutual exclusion (or a different design).
For example, what will happen if two threads call multiServer.writers.add(out); concurrently?
From the ArrayList Javadocs
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or [...])
Another problem is two calling udp_data = en.getDataFeed(cliString); concurrently. The second thread might overwrite the result of the first. You'll loose data!
What happens if one thread calls for (int i=0; i<multiServer.writers.size();i++) while another thread is busy doing multiServer.writers.add(out);? The size may have increased, before out has actually been added to the list!
public class multiServer
{
private List<PrintWriter> writers = new ArrayList<PrintWriter>();
public synchronized void addWriter(PrintWrite out) {
writers.add(out);
}
public synchronized void serveAllWriters(String data) {
for (int i=0; i<multiServer.writers.size();i++)
{
broad=multiServer.writers.get(i);
broad.println(data);
}
}
}
Now when a thread tries to add a writer, the synchronizeds will make sure no other thread is adding or printing. So multiServerThread should be fixed to use the new methods:
class multiServerThread extends Thread implements InterestingEvent
{
//...
private String udp_data;
//...
myMultiServer.addWriter(out);
//...
udp_data = en.getDataFeed(cliString);
if(udp_data!=null && udp_data.length()>0)
myMultiServer.serveAllWriters(udp_data.trim());
//...
}
There might be more problems, not sure I don't fully understand your code. The question you must ask yourself is, can another thread read and/or write the same data or object? Yes? Then you'll need proper synchronization.

Categories