Reputation: 9584
Below I have put a fragment of code to help understand my problem. I have a server code, works fine for the first time the client loads and sends a packet. After the first packet is received, the server is stuck on "accept".
I have wireshark configured for this port, and the server is getting those packets. I just wonder why accept wont return more than once. Its driving me nuts.
Server Code
public class DAPool implements Runnable {
private ServerSocket serverSocket;
private ArrayList<DA> pool;
private LinkedList<Socket> clientConnQ;
public DAPool(int newPoolSize, int serverPort) {
try {
serverSocket = new ServerSocket(serverPort, 500, InetAddress.getByName("127.0.0.1"));
} catch (IOException e) {
e.printStackTrace();
return;
}
poolSize = newPoolSize;
clientConnQ = new LinkedList<Socket>();
pool = new ArrayList<DA>(poolSize);
DA deviceThread;
for (int threads = 0; threads < poolSize; threads++) {
deviceThread = new DA();
connPool.add(deviceThread);
deviceThread.start();
}
}
public void run() {
while (true) {
Socket incomingSocket;
try {
incomingSocket = serverSocket.accept();
} catch (IOException e) {
e.printStackTrace();
return;
}
insertNewConnToQ(incomingSocket);
}
}
private class DA extends Thread {
private Socket clientSocket;
private ObjectInputStream inputObjectStream;
public DA() {
}
public void run() {
while (true) {
while (clientConnQ.isEmpty()) {
synchronized (clientConnQ) {
try {
clientConnQ.wait();
} catch (InterruptedException ignored) {
ignored.printStackTrace();
}
}
}
synchronized (clientConnQ) {
clientSocket = (Socket) clientConnQ.removeFirst();
try {
inputObjectStream = new ObjectInputStream(clientSocket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
return;
}
// Do something useful here
}
}
}
}
}
Client Code
public class SendQueue extends Thread {
LinkedList<Message> requestQ;
Message sendRequest, requestMessage;
Socket clientSocket;
OutputStream outputStream;
ObjectOutputStream objectOutputStream;
public SendQueue(Socket newClientSocket) {
requestQ = new LinkedList<Message>();
clientSocket = newClientSocket;
}
public void run() {
while (true) {
synchronized (requestQ) {
while (requestQ.isEmpty()) {
try {
requestQ.wait();
} catch (InterruptedException ignored) {
ignored.printStackTrace();
}
}
sendRequest = requestQ.removeFirst();
}
try {
outputStream = clientSocket.getOutputStream();
objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(sendRequest);
objectOutputStream.flush();
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
public int sendRequest(Message message) {
synchronized (requestQ) {
requestQ.addLast(message);
requestQ.notify();
}
return 0;
}
}
Upvotes: 1
Views: 5896
Reputation: 9584
Ok, if I got a $ for everytime I asked a silly question :)
Here goes. A client socket connects and thats when a server receives a accept call. For some silly reason I was waiting on accept for receiving further data from the client. Infact, I should just wait for something on the "stream" and then process the stream. I should not wait on the accept for that connection.
Accept is to be called to "connect" to the socket, not to receive data continuously.
Thanks for your all your help. You forced me to think about thread synchronization, the design, sockets in general and finally arrive that the solution.
Fantastic responses people. Thanks. Siddharth
Upvotes: 0
Reputation: 173
Are you sure that it is sticking on the accept call? Did you get a stacktrace that shows it waiting on accept?
Assuming it is getting stuck elsewhere I'm wondering if it isn't because clientConnQ is being held in one of your DA instances. The synchronized block covers the // Do something useful here section.
I wonder if it might work if you changed the code to be
synchronized (clientConnQ) {
clientSocket = (Socket) clientConnQ.removeFirst();
}
try {
...
Once you have your clientSocket from clientConnQ then no other instance can process that socket.
Upvotes: 2
Reputation: 3594
I don't see a timeout being set on the serverSocket.
ServerSocket.accept()
is a blocking operation so it will block until either an error occurs, a timeout occurs, or a connection is accepted.
Try
SererSocket.setSOTimeout(10000)
You also don't seem to be closing your streams when your finished.
Upvotes: 3