I have a user defined class Message, whose object I would like to pass between the client and the server.
The Message class is as follows:
import java.io.Serializable;
public class Message implements Serializable
{
String CorS;
int data_id;
int status_id;
Integer value;
boolean withdraw;
public Message()
{
CorS = null;
data_id = 0;
status_id = 0;
value = 0;
withdraw = false;
}
public Message(String CorS, int data_id, int status_id, Integer value)
{
this.CorS = CorS;
this.data_id = data_id;
this.status_id = status_id;
this.value = value;
}
public Message(boolean withdraw)
{
this.withdraw = withdraw;
}
}
The code in the client side which sends the object to the server is as follows:
Socket s = null;
ObjectInputStream in = null;
ObjectOutputStream out = null;
String hostname = null;
int port_no = 0;
HashMap<String, Integer> map = null;
Message m = null;
map = servers.get("Server" + server);
for(String key : map.keySet())
{
hostname = key;
port_no = map.get(key);
}
//System.out.println(hostname + " " + port_no);
s = new Socket(hostname, port_no);
in = new ObjectInputStream(new BufferedInputStream(s.getInputStream()));
out = new ObjectOutputStream(new BufferedOutputStream(s.getOutputStream()));
s_now = s;
m = new Message(client, data, 0, 0);
out.writeObject(m);
out.flush();
System.out.println("Sent obj");
Similarly, the code on the Server side is as follows:
while (true)
{
try
{
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(server.getInputStream()));
//ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream());
Message m = (Message) in.readObject();
System.out.println(m.value);
}
catch (IOException e)
{
e.printStackTrace();
break;
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The problem is that the object is not getting printed. The output I get is as follows:
Waiting for client on port 1051...
Just connected to /127.0.0.1:59216
Any help in this regard will be greatly appreciated. Thanks :)
You need to create the ObjectOutputStream before the ObjectInputStream at both ends.
The reason is that, as described in the Javadoc, the respective constructors write and read a stream header. So the input stream constructor can't return until the output stream constructor at the peer has executed. So if you construct both input streams first there is a deadlock.
Related
I am creating a Socket Client/Sever program that outputs the results of a fibonacci formula. I have already built the client/server connection and have tested. That part of it is working as intended. I am now trying to add in the fibonacci formula to the server but am having trouble coding the conversion of int type toSring(). The fibonacci formula is running on the server side. Code will be posted below. Thank you all for the help. I am trying to pass the clients input into fibonacci(int n) to get the desired results. If the user inputs 2, the answer should be 3, since 2 + 1 = 3 in the fibonacci numbering sequence.
Server Code:
public class ServerData {
public static int fibonacci(int n) {
int v1 = 0, v2 = 1, v3 = 0;
for(int i = 2; i <= n; i++) {
v3 = v1 + v2;
v1 = v2;
v2 = v3;
}
return v3;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ServerSocket server = null;
boolean shutdown = false;
try {
server = new ServerSocket(1236);
System.out.println("Port bound. Accepting connection");
} catch(IOException e) {
e.printStackTrace();
System.exit(-1);
}
while(!shutdown) {
Socket client = null;
InputStream input = null;
OutputStream output = null;
try {
client = server.accept();
input = client.getInputStream();
output = client.getOutputStream();
int n = input.read();
byte[] data = new byte[n];
input.read(data);
// int fibOut = fibonacci(int n);
String clientInput = new String (data, StandardCharsets.UTF_8);
clientInput.replace("\n","");
System.out.println("Client said: " + clientInput);
String response = ("Your input was [" + clientInput + "]");
output.write(response.length());
output.write(response.getBytes());
client.close();
if(clientInput.equalsIgnoreCase("shutdown")) {
System.out.println("shutting down...");
shutdown = true;
}
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
}
Client Code:
public class ClientData {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.print("Input a String: ");
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
try {
String userString = userInput.readLine();
Socket connection = new Socket("127.0.0.1", 1236);
InputStream input = connection.getInputStream();
OutputStream output = connection.getOutputStream();
output.write(userString.length());
output.write(userString.getBytes());
int n = input.read();
byte [] data = new byte[n];
input.read(data);
String serverResponse = new String(data, StandardCharsets.UTF_8);
System.out.println("Server said: " + serverResponse);
if (!connection.isClosed());
connection.close();
}
catch (IOException e ) {
e.printStackTrace();
}
}
}
If you want to send data between client and server as text, then what you need to do on the server side (after reading from input into byte[]) is to convert it into String and then parse as int.
That you can do with int number = Integer.parseInt(new String(data));.
However, your code has one more bug (in both client and server).
It's in the code that is writing string into the output stream.
Your code is doing following thing:
output.write(userString.length());
output.write(userString.getBytes());
which may give invalid results. Notice that length() returns length of the String, which means: number of characters.
However what you need is number of bytes. Those two values will be different in case your string contains characters from outside of ascii range.
I'm new to socket. I want to make a client-server program but I have a problem when it comes to printing messages on the side of the server. That leads me to believe there is a problem in my Client class when it is sending the messages. The first message that is sent from client to server is delivered fine but the rest aren't printed even though the sequence number is printed.
Here are both classes:
Client class:
public class Cliente extends Conexion {
private String mensaje;
private String recibeTeclado;
int numSec = 0;
String tipo = "0";
private int num;
int c;
public Cliente() throws IOException{
super("cliente");
}
public void startClient() {
try {
salidaServidor = new DataOutputStream(cs.getOutputStream());
Scanner lee = new Scanner(System.in);
System.out.println("How many messages do you want to send?");
num = lee.nextInt();
salidaServidor.writeUTF(":" + num + "\n");
for (int i = 1; i <= num; i++) {
numSec++;
System.out.println("Enter the message: ");
recibeTeclado = lee.next();
mensaje = tipo + ":" + Integer.toString(numSec) + ":" + recibeTeclado + "\n";
salidaServidor.writeUTF(mensaje);
salidaServidor.flush();
BufferedReader in = new BufferedReader (new InputStreamReader (cs.getInputStream()));
String mensajeDelServidor = in.readLine();
System.out.println("Status : " + mensajeDelServidor);
}
cs.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Server class:
public class Servidor extends Conexion{
String nuevo;
int numSec=0;
String tipo="1";
int num;
String [] n;
public Servidor() throws IOException{super("servidor");}
public void startServer() {
try {
System.out.println("Waiting...");
cs = ss.accept();
BufferedReader numString = new BufferedReader(new InputStreamReader(cs.getInputStream()));
n=numString.readLine().split(":");
num=Integer.parseInt(n[1]);
for(int i=1; i<=num; i++) {
salidaCliente=new DataOutputStream(cs.getOutputStream());
numSec++;
System.out.println(numSec);
nuevo= tipo +":"+ Integer.toString(numSec) +":"+ "Received\n";
salidaCliente.writeUTF(nuevo);
salidaCliente.flush();
BufferedReader entrada = new BufferedReader(new InputStreamReader(cs.getInputStream()));
boolean band=false;
while((mensajeServidor=entrada.readLine())!=null && !band) {
String[] arrSplit = mensajeServidor.split(":");
System.out.println(arrSplit[2]);
band=true;
}
}
System.out.println("Fin de la conexión");
ss.close();
cs.close();
}catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
[Updated, thanks to #user207421's comment]
2 solutions
Keep using DataOutputStream.writeUTF
Then you have to use DataInputStream.readUTF instead of BufferedReader.readLine.
And if you want to use '\n' as a separator, you will have to detect such characters
Keep using BufferedReader.readLine
Then you have to use an output stream method like Writer.write instead of DataOutputStream.writeUTF.
Use only one BufferedReader instance, on server side at least (numString will keep buffered data that will not be available for the entrada instance).
For UTF-8, use:
BufferedReader in = new BufferedReader(new InputStreamReader(cs.getInputStream(), "UTF-8"));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(cs.getOutputStream(), "UTF-8"));
On the client side, you should use a PrintWriter instead of a DataOutputStream to write data to the server:
salidaServidor = new PrintWriter(cs.getOutputStream(), true);
On the server side, 'salidaCliente' should also be a PrintWriter.
I'm working on some code to interact with a server and send a file in 1000 byte chunks. I want to use setSoTimeout to resend a packet after 5 seconds if I have not received an ACK from the server by then. I have searched for the answer to this but to no avail. Here are some links i checked out and attempted:
What is the functionality of setSoTimeout and how it works?
how to use socket.setSoTimeout()?
setSotimeout on a datagram socket
I am under the impression that when the timer is going you are continuously waiting for the ACK. Is this the case? I am never receiving an ACK from the server, although I was at one point before.
import java.net.*;
import java.io.*;
import java.util.*;
public class FTPClient {
Socket tcpSocket;
DatagramSocket udpSocket;
DataInputStream dataIn;
DataOutputStream dataOut;
BufferedReader br;
String fileName;
int time;
int portNum;
/**
* Constructor to initialize the program
*
* #param serverName server name
* #param server_port server port
* #param file_name name of file to transfer
* #param timeout Time out value (in milli-seconds).
*/
public FTPClient(String server_name, int server_port, String file_name, int timeout) {
System.out.println("Server Name: " + server_name + " Server Port: " + server_port
+ " File Name: " + file_name + " Timeout: " + timeout);
fileName = file_name;
time = timeout;
portNum = server_port;
try {
Socket tcpSocket = new Socket(server_name, server_port);
dataIn = new DataInputStream(tcpSocket.getInputStream());
dataOut = new DataOutputStream(tcpSocket.getOutputStream());
br = new BufferedReader(new InputStreamReader(System.in));
}
catch (Exception ex) {
System.out.println("Exception in FTPClient initialization: " + ex);
}
}
/**
*Send file content as Segments
*
*/
public void send() {
try {
File f = new File(fileName);
if (!f.exists()) {
System.out.println("File does not exist...");
return;
}
System.out.println("Sending filename (" + fileName + ") to server.");
dataOut.writeUTF(fileName);
byte msgFromServer = dataIn.readByte();
if (msgFromServer == 0) {
System.out.println("Server ready to receive file");
}
// Create a UDP socket to send the file to the server
DatagramSocket udpSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
FileInputStream fileIn = new FileInputStream(f);
int seqNum = 0;
int i = 0;
Boolean received = false;;
byte[] chunks = new byte[1000];
int rc = fileIn.read(chunks);
while(rc != -1)
{
System.out.println("Iteration #: " + i);
System.out.println(rc);
// rc should contain the number of bytes read in this operation.
//if (rc < 1000) {
//System.out.println("Bytes read less than 1000");
//System.out.println("Sequence Number: " + seqNum);
//System.out.println("Packet too small to send");
//}
System.out.println("Bytes read greater than 1000");
System.out.println("Sequence Number: " + seqNum);
while (received == false) {
System.out.println("You are looping and sending again");
transferPacket(seqNum, IPAddress, chunks);
received = getResponse();
}
rc = fileIn.read(chunks);
if (seqNum == 1) {
seqNum = 0;
}
else {
seqNum = 1;
}
i++;
}
}
catch (Exception e) {
System.out.println("Error: " + e);
}
}
public Boolean getResponse() {
try {
DatagramSocket udpSocket = new DatagramSocket();
System.out.println("You are in getResponse()");
byte[] receiveData = new byte[1000];
udpSocket.setSoTimeout(time); // set timer
while (true) {
try {
System.out.println("You are receiving a packet");
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
udpSocket.receive(receivePacket);
Segment unwrap = new Segment(receivePacket);
int num = unwrap.getSeqNum();
System.out.println("Received ACK with Sequence Number: " + num);
return true;
}
catch (SocketTimeoutException t) {
System.out.println("Timeout: return false to send()");
return false;
}
}
}
catch (Exception e) {
System.out.println("You don't wanna be here");
return false;
}
}
public void transferPacket(int seqNum, InetAddress IPAddress, byte[] chunks) {
try {
DatagramSocket udpSocket = new DatagramSocket();
byte[] sendData = new byte[1000];
Segment s = new Segment(seqNum, chunks);
sendData = s.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, portNum);
udpSocket.send(sendPacket);
System.out.println("Sent Packet with sequence number " + seqNum);
}
catch (Exception e) {
System.out.println("Exception in transferPacket: " + e);
}
}
/**
* A simple test driver
*
*/
public static void main(String[] args) {
String server = "localhost";
String file_name = "";
int server_port = 8888;
int timeout = 5000; // milli-seconds (this value should not be changed)
// check for command line arguments
if (args.length == 3) {
// either provide 3 parameters
server = args[0];
server_port = Integer.parseInt(args[1]);
file_name = args[2];
}
else {
System.out.println("Wrong number of arguments, try again.");
System.out.println("Usage: java FTPClient server port file");
System.exit(0);
}
FTPClient ftp = new FTPClient(server, server_port, file_name, timeout);
System.out.printf("Sending file \'%s\' to server...\n", file_name);
try {
ftp.send();
}
catch (Exception e) {
System.out.println("Exception: " + e);
}
System.out.println("File transfer completed.");
}
}
You need to keep using the same UDP socket for the life of the application, not a new one per packet, and use it for both sending and receiving.
At present you are also leaking UDP sockets like a firehose.
i've this problem, I've a Multithreaded server running. here it's the code:
ServerSocket serverSocket=null; // defining a server socket to listen data
Socket clientSocket = null; // defining a client socket to send data
final int port=8080;
int i=0;
try {
serverSocket = new ServerSocket(port); // Opening a server socket to listen for client calls
System.out.println("Server started.");
} catch (Exception e) {
System.err.println("Port already in use.");
System.exit(1);
}
while (true) {
try {
clientSocket = serverSocket.accept(); //binding server socket to client socket incoming call and accepting call
System.out.println("Accepted connection : " + clientSocket);
i=i+1;
Thread t = new Thread(new newClientHandler(clientSocket, NodePRs[1]),"thread"+i); //Create a new thread to handle the single call coming from one client
System.out.println("Thread "+t.getName()+" is starting");
t.start(); //Starting the run method contained in newCLIENTHandler class
} catch (Exception e) {
System.err.println("Error in connection attempt.");
}
}//end while
All that i need is to let the children thread (opened every time a client request come) pass (like a function return) 4 variables when the children thread die. The newClientHandler code is this:
public class newClientHandler implements Runnable {
private final static int FILE_SIZE=6022386;
private Socket clientSocket;
private PaillierPrivateKey PrivKey;
ServerSocket servSock;
BigInteger[] msg = null;
BigInteger preamble = null;
int bytesRead;
int current = 0;
DataOutputStream dos = null;
BufferedReader dis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
int msgtype=-1;
int num_of_rx_cnks=-1;
public newClientHandler(Socket client, PaillierPrivateKey PR) {
this.clientSocket = client;
this.PrivKey = PR;
}
//I CAN RECEIVE 3 TYPES OF MESSAGES: SHARE, THE ENCRYPTED PASSWORD, THE 4 PDMS
public void run() {
try{
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
preamble = (BigInteger) ois.readObject();
System.out.println("Received Preamble is:"+preamble);
oos.writeObject("Received preamble");
msg =(BigInteger[]) ois.readObject();
System.out.println("Received Message is:"+msg+"\n"+msg[0]+"\n"+msg[2]);
String sPlain = Utilities.bigIntegerToString(preamble);
String[] splitArr=Pattern.compile("-").split(sPlain);
msgtype=Integer.parseInt(splitArr[0]);
num_of_rx_cnks=Integer.parseInt(splitArr[1]);
System.out.println("Message type: "+msgtype+"\n"+"Number of received cnks: "+num_of_rx_cnks);
//a questo punto ho i miei 29 biginteger. Li devo sistemare uno accanto all'altro e rimettere nel file.
switch(msgtype){
case 1: //Share received
System.out.println("Received the share");
for(int i=0;i<num_of_rx_cnks;i++){
String name = new String();
if(i<9){
name="Cyph2"+".00"+(i+1);
}
if(i>8){
name="Cyph2"+".0"+(i+1);
}
Utilities.newBigIntegerToFile(msg[i], name);
}
Utilities.retrieveShare(PrivKey, 2,"myShare");
int l, w;
BigInteger v, n, shares, combineSharesConstant;
BigInteger[] viarray=new BigInteger[5];
PaillierPrivateThresholdKey[] res = null;
try {
FileReader File= new FileReader("myShare");
BufferedReader buf=new BufferedReader(File);
String line=buf.readLine();
l = Integer.parseInt(line.split(":")[1]);
line = buf.readLine();
w = Integer.parseInt(line.split(":")[1]);
line = buf.readLine();
v = new BigInteger(line.split(":")[1]);
line = buf.readLine();
n = new BigInteger(line.split(":")[1]);
line = buf.readLine();
combineSharesConstant = new BigInteger(line.split(":")[1]);
line = buf.readLine();
shares = new BigInteger(line.split(":")[1]);
for(int i=0; i<5; i++){
line = buf.readLine();
viarray[i] = BigInteger.ZERO;
}
SecureRandom rnd = new SecureRandom();
PaillierPrivateThresholdKey result = new PaillierPrivateThresholdKey(n, l, combineSharesConstant, w, v,
viarray, shares, 2, rnd.nextLong());//il 2 qua è il nodeID
}catch(IOException e){
System.out.println(e);
}
break;
case 2: // Session Secret received
break;
case 3: //PDM received
break;
}//end switch
}catch(IOException ioe){
System.out.println(ioe);
}catch(ClassNotFoundException cnfe){
System.out.println(cnfe);
}finally {
try{
if (dis != null) dis.close();
if (dos != null) dos.close();
if (clientSocket!=null) clientSocket.close();
}catch (IOException e){
System.out.println(e);
}
}
}
}
I'd like to pass l, w, v, n and so on to let my main thread do some processing. How can i modify my code to do it?
Use a Callable instead of a Runnable.
Bundle the 4 variables into a class and implement Callable<YourNewClass>. Run your callable with an executor and you'll get the results in a Future<YourNewClass>.
I am aware of the fact that the following code may seem vulgar, but I am new to these things and just tried everything in order to get it to work..
Problem: Even though I am using (possible in a wrong way) a CyclicBarrier, one - and seems to always be the same - thread stops too soon and prints out his vector, leaving 1 out of 11 of those "Incoming connection" messages absent. There is probably something terribly wrong with the last iteration of my loop, but I can't seem to find what exactly.. Now the program just loops waiting to process the last connection.
public class VectorClockClient implements Runnable {
/*
* Attributes
*/
/*
* The client number is store to provide fast
* array access when, for example, a thread's own
* clock simply needs to be incremented.
*/
private int clientNumber;
private File configFile, inputFile;
int[] vectorClock;
/*
* Constructor
* #param
* - File config
* - int line
* - File input
* - int clients
*/
public VectorClockClient(File config, int line, File input, int clients) {
/*
* Make sure that File handles aren't null and that
* the line number is valid.
*/
if (config != null && line >= 0 && input != null) {
configFile = config;
inputFile = input;
clientNumber = line;
/*
* Set the array size to the number of lines found in the
* config file and initialize with zero values.
*/
vectorClock = new int[clients];
for (int i = 0; i < vectorClock.length; i++) {
vectorClock[i] = 0;
}
}
}
private int parsePort() {
int returnable = 0;
try {
FileInputStream fstream = new FileInputStream(configFile.getName());
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine = "";
for (int i = 0; i < clientNumber + 1; i++) {
strLine = br.readLine();
}
String[] tokens = strLine.split(" ");
returnable = Integer.parseInt(tokens[1]);
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("[" + clientNumber + "] returned with " + returnable + ".");
return returnable;
}
private int parsePort(int client) {
int returnable = 0;
try {
FileInputStream fstream = new FileInputStream(configFile.getName());
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine = "";
for (int i = 0; i < client; i++) {
strLine = br.readLine();
}
String[] tokens = strLine.split(" ");
returnable = Integer.parseInt(tokens[1]);
}
catch (Exception e) {
e.printStackTrace();
}
return returnable;
}
private int parseAction(String s) {
int returnable = -1;
try {
FileInputStream fstream = new FileInputStream(configFile.getName());
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String[] tokens = s.split(" ");
if (!(Integer.parseInt(tokens[0]) == this.clientNumber + 1)) {
return -1;
}
else {
if (tokens[1].equals("L")) {
vectorClock[clientNumber] += Integer.parseInt(tokens[2]);
}
else {
returnable = Integer.parseInt(tokens[2]);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return returnable;
}
/*
* Do the actual work.
*/
public void run() {
try {
InitClients.barrier.await();
}
catch (Exception e) {
System.out.println(e);
}
int port = parsePort();
String hostname = "localhost";
String strLine;
ServerSocketChannel ssc;
SocketChannel sc;
FileInputStream fstream;
DataInputStream in;
BufferedReader br;
boolean eof = false;
try {
ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(hostname, port));
ssc.configureBlocking(false);
fstream = new FileInputStream("input_vector.txt");
in = new DataInputStream(fstream);
br = new BufferedReader(new InputStreamReader(in));
try {
InitClients.barrier.await();
}
catch (Exception e) {
System.out.println(e);
}
while (true && (eof == false)) {
sc = ssc.accept();
if (sc == null) {
if ((strLine = br.readLine()) != null) {
int result = parseAction(strLine);
if (result >= 0) {
//System.out.println("[" + (clientNumber + 1)
//+ "] Send a message to " + result + ".");
try {
SocketChannel client = SocketChannel.open();
client.configureBlocking(true);
client.connect(
new InetSocketAddress("localhost",
parsePort(result)));
//ByteBuffer buf = ByteBuffer.allocateDirect(32);
//buf.put((byte)0xFF);
//buf.flip();
//vectorClock[clientNumber] += 1;
//int numBytesWritten = client.write(buf);
String obj = Integer.toString(clientNumber+1);
ObjectOutputStream oos = new
ObjectOutputStream(
client.socket().getOutputStream());
oos.writeObject(obj);
oos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
else {
eof = true;
}
}
else {
ObjectInputStream ois = new
ObjectInputStream(sc.socket().getInputStream());
String clientNumberString = (String)ois.readObject();
System.out.println("At {Client[" + (clientNumber + 1)
+ "]}Incoming connection from: "
+ sc.socket().getRemoteSocketAddress()
+ " from {Client[" + clientNumberString + "]}");
sc.close();
}
try {
InitClients.barrier.await();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
printVector();
}
private void printVector() {
System.out.print("{Client[" + (clientNumber + 1) + "]}{");
for (int i = 0; i < vectorClock.length; i++) {
System.out.print(vectorClock[i] + "\t");
}
System.out.println("}");
}
}
To clarify, here are the formats of the files used. Config contains hostnames and ports used by clients that are threads and input file's rows mean either "this client sends a message to that client" or "this client increments his logical clock by some constant value".
1 M 2 (M means sending a message)
2 M 3
3 M 4
2 L 7 (L means incrementing clock)
2 M 1
...
127.0.0.1 9000
127.0.0.1 9001
127.0.0.1 9002
127.0.0.1 9003
...
I would look at the logic related to when you are expecting an incoming socket connection. From your question it looks like you expect a certain number of incoming socket connections (potentially an incoming connection after every outgoing message?). Since you are using non-blocking I/O on the incoming socket it is always possible that your while statement loops before an incoming socket could be established. As a result, a thread would be able to continue and read the next line from the file without receiving a connection. Since your end state is reached once the end of the file is reached, it is possible that you may miss an incoming socket connection.
I would add some simple print outs that displays when you read from the file, when you send a message and when you receive an incoming connection. That should quickly tell you whether or not a particular thread is missing an expected incoming connection. If it turns out that the problem is due to the non-blocking I/O, then you may need to disable non-blocking I/O when you expect an incoming socket or implement a control that keeps track of how many incoming sockets you expect and continues until that goal is met.
Hope this helps.