Byte Buffer Is getting Corrupts in TCP Response - java

I have have Tcp Server
public class SomeServer implements Runnable{
private static final int BUFFER_SIZE = 4096;
private Selector selector;
private int port;
private boolean runserver = true;
private ServerSocketChannel mySocketChannel;
private ServerSocket serverSocket;
public SomeServer(int port) {
this.port = port;
}
#Override
public void run() {
startServer();
}
private void startServer() {
try {
selector = Selector.open();
InetAddress hostIP = InetAddress.getByName("127.0.0.1");
mySocketChannel = ServerSocketChannel.open();
serverSocket = mySocketChannel.socket();
InetSocketAddress address = new InetSocketAddress(hostIP, port);
log.info("Setting up SomeServer with on {} with port {} ", hostIP, port);
serverSocket.bind(address);
mySocketChannel.configureBlocking(false);
int ops = mySocketChannel.validOps();
mySocketChannel.register(selector, ops, null);
while (runserver) {
log.info("Server running");
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> i = selectedKeys.iterator();
while (i.hasNext()) {
SelectionKey key = i.next();
if (key.isAcceptable()) {
processAcceptEvent(mySocketChannel, key);
} else if (key.isReadable()) {
processReadEvent(key);
}
i.remove();
}
}
} catch (Exception e) {
log.error("Something gone wrong in SomeServer {}", e);
}
}
private void processAcceptEvent(ServerSocketChannel mySocket, SelectionKey key) throws IOException {
log.info("Connection Accepted...");
// Accept the connection and make it non-blocking
SocketChannel myClient = mySocket.accept();
myClient.configureBlocking(false);
// Register interest in reading this channel
myClient.register(selector, SelectionKey.OP_READ);
}
private void processReadEvent(SelectionKey key) throws Exception {
log.info("Inside processReadEvent...");
// create a ServerSocketChannel to read the request
SocketChannel myClient = (SocketChannel) key.channel();
ByteBuffer myBuffer = ByteBuffer.allocate(BUFFER_SIZE);
myBuffer.order(ByteOrder.BIG_ENDIAN);
int radBytes= myClient.read(myBuffer);
if(radBytes ==-1)
return; //means connection is closed
ByteBuffer responseBuffer = clone(execute(myBuffer));
if(responseBuffer ==null){
return;
}
int byteswritten = myClient.write(responseBuffer);
log.info("bytesWritten...: {}", byteswritten);
}
public ByteBuffer execute(ByteBuffer requestBuffer) throws Exception {
final CharsetEncoder myEncoder = Charset.forName("ISO-8859-1").newEncoder();
final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;
CharsetDecoder myDecoder = Charset.forName("ISO-8859-1").newDecoder();
//Process Request
final ByteBuffer processBuffer = clone(requestBuffer);
// processBuffer.flip();
int bufferSize = processBuffer.getInt();
String request = myDecoder.decode(processBuffer).toString().trim();
int requestLength=request.length();
if(requestLength<8){
log.info("Connection closed ");
return null;
}
String firstName = request.substring(0,8);
int requestBodyLength= requestLength-firstName.length();
String command = request.substring(8,requestLength-1);
processBuffer.flip();
//Build-Response
processBuffer.clear();
String response="some response";
int responselength = response.length()+firstName.length()+4;
processBuffer.putInt(responselength);
processBuffer.put(myEncoder.encode(CharBuffer.wrap(firstName)));
processBuffer.put(myEncoder.encode(CharBuffer.wrap(response)));
processBuffer.put(END_OF_MESSAGE_BYTE);
processBuffer.flip();
return processBuffer;
}
public static ByteBuffer clone(ByteBuffer original) {
if(original == null)
return null;
ByteBuffer clone = ByteBuffer.allocate(original.capacity());
original.rewind();//copy from the beginning
clone.put(original);
original.rewind();
clone.flip();
return clone;
}
}
Sending some message and except some response back
Client Side :Reading Response
public class Mycleint {
priavte SocketCahnnel mySocket;
priavte String name;
final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;
public Mycleint (String name , InetSocketAddress inetAddress){
this.name=name;
mySocket = SocketChannel.open();
mySocket.connect(inetAddress);
}
private String sendRequest(String request) throws IOException {
final CharsetEncoder myEncoder = Charset.forName("ISO-8859-1").newEncoder();
int requestLength = 12 + request.length() + 1;
ByteBuffer buffer = ByteBuffer.allocate(requestLength);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putInt(requestLength);
buffer.put(myEncoder.encode(CharBuffer.wrap(name)));
buffer.put(myEncoder.encode(CharBuffer.wrap(request)));
buffer.put();
buffer.flip();
mysocket.write(buffer);
return readResponse();
}
private String readResponse(SocketChannel mySocket) throws IOException {
CharsetDecoder myDecoder = Charset.forName("ISO-8859-1").newDecoder();
ByteBuffer responseHeaderBuf = ByteBuffer.allocate(12);
responseHeaderBuf.order(ByteOrder.BIG_ENDIAN);
int bytesRead = 0;
do {
bytesRead = mySocket.read(responseHeaderBuf);
} while (bytesRead != -1 && responseHeaderBuf.position() < 12);
if (bytesRead == -1) {
throw new IOException(" : Remote connection closed unexpectedly");
}
responseHeaderBuf.flip();
int lengthField = responseHeaderBuf.getInt();
int responseLength = lengthField - responseHeaderLength;
String responseName = myDecoder.decode(responseHeaderBuf).toString();
ByteBuffer responseBuf = ByteBuffer.allocate(responseLength);
do {
bytesRead = mySocket.read(responseBuf);
} while (bytesRead != -1 && responseBuf.position() < responseLength);
if (bytesRead == -1) {
throw new IOException(name + " : Remote connection closed unexpectedly");
}
responseBuf.flip();
if (responseBuf.get(responseBuf.limit() - 1) == END_OF_MESSAGE_BYTE) {
responseBuf.limit(responseBuf.limit() - 1);
}
String response = myDecoder.decode(responseBuf).toString();
return response;
}
}
I leave the SocketChannel open indefinitely in client side .
When I decode the response in client responseHeaderBuf.getInt(), It works correct during the first time. but second time the data get corrupted when i decode.
Also if a socket is used to send request everything works as expected,but i want to reuse the socket i created
Example, if server sent 28 processBuffer.putInt(28); client says it received responseHeaderBuf.getInt()--> 721420288 ,
Could some one help and tell me what I'm doing wrong.

Related

Correct way to send a string through tcp using java nio

I'm trying to send/recv a String using a Bytebuffer of fixed dimension, no matter what dimension is the string
Both client and server are composed by 2 classes, the main and the Client/Server, witch sould encapsulate the implementation of sending/receiving a string
For now the 2 main should work ad an echo client/server with the possibility of having multiple clients using a selector
Here is CLient side:
public class Client {
private SocketChannel clientChannel;
private int bufferDim;
public WinsomeClient(String host, int port, int bufferDim) throws IOException{
this.clientChannel = SocketChannel.open(new InetSocketAddress(host, port));
this.bufferDim = b.bufferDim;
System.out.println("Connected to " + b.serverHost + b.serverPort);
}
public String send(String request) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(bufferDim * Character.BYTES);
int iters = (int) Math.ceil(request.length / (float) bufferDim);
System.out.println("Iters: " + iters);
int offset = 0;
int length;
for(int i=0; i<iters; i++){
length = Math.min(bufferDim, request.length - offset);
buffer.put(request.getBytes(), offset, length);
buffer.flip();
while (buffer.hasRemaining()){
clientChannel.write(buffer);
}
buffer.clear();
offset += bufferDim;
}
System.out.println("Sent "+request.getMessage());
StringBuilder stringBuilder = new StringBuilder();
buffer.rewind();
while (clientChannel.read(buffer)>0){
buffer.flip();
while (buffer.hasRemaining()){
stringBuilder.append((char) buffer.get());
}
buffer.clear();
}
System.out.println("Recv" + stringBuilder.toString());
return stringBuilder.toString();
}
public class MainClient {
public static void main(String[] args) {
int port = 1919;
String host = "127.0.0.1";
int bufDim = 1024;
Client client ;
try{
client = new Client(host, port, bufDim);
for(String expected = "a"; ; expected+="a"){
System.out.println(expected);
String response = client.send(expected);
if(!response.equals(expected){
System.err.println("Expected " + expected + "; was " + response);
break;
}
System.out.println(response);
}
} catch (IOException e){
e.printStackTrace();
}
}
}
Server side:
public class Server {
private SocketChannel clientChannel;
private int bufferDim;
public WinsomeServer(SocketChannel clientChannel, int bufferDim){
this.clientChannel = clientChannel;
this.bufferDim = bufferDim;
}
public String recv() throws IOException{
ByteBuffer buffer = ByteBuffer.allocate(bufferDim * Character.BYTES);
buffer.rewind();
StringBuilder stringBuilder = new StringBuilder();
while (clientChannel.read(buffer)>0){
buffer.flip();
while (buffer.hasRemaining()){
stringBuilder.append((char) buffer.get());
}
buffer.clear();
}
System.out.println("Recv " + stringBuilder.toString());
return stringBuilder.toString();
}
public void send(String response) throws IOException{
ByteBuffer buffer = ByteBuffer.allocate(bufferDim * Character.BYTES);
buffer.rewind();
int iters = (int) Math.ceil(response.getMessageLength() / (float)bufferDim);
System.out.println("Iters: " + iters);
int offset = 0;
int length;
for(int i=0; i<iters; i++){
length = Math.min(bufferDim, response.getMessageLength()-offset);
buffer.put(response.getMessage().getBytes(), offset, length);
buffer.flip();
while (buffer.hasRemaining()){
clientChannel.write(buffer);
}
buffer.clear();
offset += bufferDim;
}
System.out.println("Sent "+ response.getMessage());
}
}
public class MainServer {
public static void main(String[] args) {
ServerSocketChannel serverChannel;
Selector selector = null;
ServerSocket serverSocket;
InetSocketAddress inetSocketAddress;
int port=1919;
System.out.println("Listening for connections on port " + port);
try{
serverChannel = ServerSocketChannel.open();
serverSocket = serverChannel.socket();
inetSocketAddress = new InetSocketAddress(port);
serverSocket.bind(inetSocketAddress);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e){
e.printStackTrace();
return;
}
while (true){
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
try {
if(key.isAcceptable()){
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
else if(key.isReadable()){
System.out.println("Reading...");
SocketChannel client = (SocketChannel) key.channel();
Server server = new Server(client);
String request = server.recv();
SelectionKey key1 = client.register(selector, SelectionKey.OP_WRITE);
key1.attach(request);
}
else if(key.isWritable()){
System.out.println("Writing...");
SocketChannel client = (SocketChannel) key.channel();
Server server = new Server(client);
String request = (String) key.attachment();
request.append("Echoed by server");
server.send(request);
client.register(selector, SelectionKey.OP_READ);
}
}
catch (IOException e){
key.cancel();
try {
key.channel().close();
} catch (IOException ee){
}
}
iterator.remove();
}
}
}
}
However, after receiving the string and sending it back, the client is not recieving it.
Anyone can figure out where is the problem?
Server output:
Listening for connections on port 1919
Accepted connection from java.nio.channels.SocketChannel[connected local=/127.0.0.1:1919 remote=/127.0.0.1:51504]
Reading...
Recv a
Writing...
Writing... a1
Iters: 1
Sent a
Reading...
Client output:
Connected to 127.0.0.11919
a
Iters: 1
Sent a

Getting extra bytes in received file using java scoket

I have implemented a file transfer program using java socket. In this program, a file is sent from the client and its then downloaded in the Server. The program works almost correctly but the problem is the length of the received byte is always greater than the byte length sent from the client. for example, I sent 678888589 bytes from the client, but when I check the length of the received file at the server, I got 678925260 bytes. And for that reason, I am getting different checksum on the server side.
Here is my code:
Client Class:
public class Client
{
final static int ServerPort = 1234;
public static final int BUFFER_SIZE = 1024 * 50;
private static byte[] buffer;
public static void main(String args[]) throws UnknownHostException, IOException
{
Scanner scn = new Scanner(System.in);
buffer = new byte[BUFFER_SIZE];
for(int i=0;i<8;i++) {
Socket s1 = new Socket(ip, ServerPort);
DataOutputStream dos1 = new DataOutputStream(s1.getOutputStream());
SendMessage message = new SendMessage(s1, "test.mp4",dos1);
Thread t = new Thread(message);
System.out.println("Adding this client to active client list");
t.start();
}
}
}
class SendMessage implements Runnable{
String file_name;
Socket s;
public final int BUFFER_SIZE = 1024 * 50;
private byte[] buffer;
DataOutputStream dos;
public SendMessage(Socket sc,String file_name,DataOutputStream dos) {
this.file_name = file_name;
this.s=sc;
buffer = new byte[BUFFER_SIZE];
this.dos = dos;
}
#Override
public void run() {
File file = new File(file_name);
try {
sendFile(file, dos);
dos.close();
while(true) {
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
public void sendFile(File file, DataOutputStream dos) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE+1];
if(dos!=null&&file.exists()&&file.isFile())
{
FileInputStream input = new FileInputStream(file);
dos.writeLong(file.length());
System.out.println(file.getAbsolutePath());
int read = 0;
int totalLength = 0;
while ((read = input.read(buffer)) != -1) {
dos.write(buffer);
totalLength +=read;
System.out.println("length "+read);
}
input.close();
System.out.println("File successfully sent! "+totalLength);
}
}
}
Server Class
// Server class
public class Server
{
// Vector to store active clients
static Vector<ClientHandler> ar = new Vector<>();
// counter for clients
static int i = 0;
public static void main(String[] args) throws IOException
{
// server is listening on port 1234
ServerSocket ss = new ServerSocket(1234);
Socket s;
// running infinite loop for getting
// client request
while (true)
{
// Accept the incoming request
s = ss.accept();
System.out.println("New client request received : " + s);
// obtain input and output streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
System.out.println("Creating a new handler for this client...");
// Create a new handler object for handling this request.
ClientHandler mtch = new ClientHandler(s,"client " + i, dis, dos);
// Create a new Thread with this object.
Thread t = new Thread(mtch);
System.out.println("Adding this client to active client list");
// add this client to active clients list
ar.add(mtch);
// start the thread.
t.start();
// increment i for new client.
// i is used for naming only, and can be replaced
// by any naming scheme
i++;
}
}
}
// ClientHandler class
class ClientHandler implements Runnable
{
Scanner scn = new Scanner(System.in);
private String name;
final DataInputStream dis;
final DataOutputStream dos;
Socket s;
boolean isloggedin;
public static final int BUFFER_SIZE = 1024*50;
private byte[] buffer;
// constructor
public ClientHandler(Socket s, String name,
DataInputStream dis, DataOutputStream dos) {
this.dis = dis;
this.dos = dos;
this.name = name;
this.s = s;
this.isloggedin=true;
buffer = new byte[BUFFER_SIZE];
}
#Override
public void run() {
String received;
BufferedOutputStream out = null;
String outputFile = "out_"+this.name+".mp4";
BufferedInputStream in = null;
try {
in = new BufferedInputStream(s.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
out = new BufferedOutputStream(new FileOutputStream(outputFile));
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// while (true)
// {
try
{
long length = -1;
length = dis.readLong();
if(length!=-1)System.out.println("length "+length);
// String checkSum = dis.readUTF();
// System.out.println(checkSum);
int len=0;
long totalLength = 0;
// int len = 0;
while ((len = in.read(buffer,0,BUFFER_SIZE)) > 0) {
out.write(buffer, 0, len);
totalLength+=len;
// if(len<BUFFER_SIZE)break;
// System.out.println("length "+len);
if(len<=0)break;
}
File file = new File(outputFile);
System.out.println("total length1 "+totalLength+ " dif "+(totalLength-length));
System.out.println("output length "+file.length());
} catch (IOException e) {
e.printStackTrace();
}
}
private static String checksum(String filepath, MessageDigest md) throws IOException {
// file hashing with DigestInputStream
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md)) {
while (dis.read() != -1) ; //empty loop to clear the data
md = dis.getMessageDigest();
}
// bytes to hex
StringBuilder result = new StringBuilder();
for (byte b : md.digest()) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
It would be great if anyone can tell me what I am doing wrong. also, how can I verify the checksum on serverside. Another issue is the server side code get blocked in this block.
while ((len = in.read(buffer,0,BUFFER_SIZE)) > 0) {
out.write(buffer, 0, len);
System.out.println("length "+len);
if(len<=0)break;
}
It can't break the loop unless the client is disconnected. Although the file is recieved properly.
Regards.
You made a small mistake on the client code. You were writing out the full buffer instead of what is read from the file.
while ((read = input.read(buffer)) != -1) {
dos.write(buffer,0,read);
totalLength += read;
System.out.println("length " + read);
}

My socket isn't sending or receiving bytearrays

I'm trying to send bytes and receive them over my socket connection but they're not doing either. I'm not sure if its a problem to do with the way i'm sending the bytes and strings or because I don't know how to read from server and client.
Client
public class Client implements Runnable {
private Socket socket;
private ByteArrayOutputStream buffer;
private OutputStream output;
private Stage stage;
public Client() {
try {
this.socket = new Socket("localhost", 1337);
this.socket.setTcpNoDelay(true);
this.socket.setKeepAlive(true);
this.output = this.socket.getOutputStream();
InputStream input = this.socket.getInputStream();
this.buffer = new ByteArrayOutputStream();
Thread connection = new Thread(this);
connection.start();
this.sendPacket(0, ByteBuffer.allocate(16 + "TEST".length()).putInt("TEST".length()).put("TEST".getBytes(Constants.UTF8)).array());
System.out.println("[CLIENT] Successfully connected to server.");
} catch (Exception e) {
IOUtils.output("[CLIENT] Error when connecting to server.");
System.exit(1337);
}
}
#Override
public void run() {
try {
while (this.connected()) {
byte[] bytes = this.buffer.toByteArray();
Constants.received += bytes.length;
if (bytes.length < 8) return;
ByteBuffer cbuf = ByteBuffer.wrap(bytes);
int size = cbuf.getInt();
int id = cbuf.getInt();
if (bytes.length < size + 8) continue;
byte[] data = Arrays.copyOfRange(bytes, 8, 8 + size);
this.processPacket(id, data);
this.buffer.close();
(this.buffer = new ByteArrayOutputStream()).write(bytes, 8 + size, bytes.length - 8 - size);
}
System.out.println("[CLIENT] Disconnected from server.");
System.exit(1337);
} catch (Exception e) {
e.printStackTrace();
}
}
private void processPacket(int id, byte[] bytes) {
ByteBuffer data = ByteBuffer.wrap(bytes);
if (id == 0) {
System.out.println("Received packet from server with id 0");
} else if (id == 1) {
System.out.println("Received packet from server with id 1");
}
}
private void sendPacket(int id, byte[] data) {
try {
ByteBuffer bytebuffer = ByteBuffer.allocate(8 + data.length);
bytebuffer.putInt(data.length);
bytebuffer.putInt(id);
bytebuffer.put(data);
byte[] bytes = bytebuffer.array();
Constants.sent += bytes.length;
this.output.write(bytes);
this.output.flush();
} catch (IOException e) {
try {
socket.close();
} catch (IOException io) {
IOUtils.output("[CLIENT] Error with client.");
System.exit(1337);
}
}
}
private boolean connected() {
return this.socket.isConnected() && !this.socket.isInputShutdown() && !this.socket.isOutputShutdown() && !this.socket.isClosed();
}
}
ServerHandler
public class Handler implements Runnable {
private Socket socket;
private ByteArrayOutputStream buffer;
private OutputStream output;
public Handler(Socket socket) {
this.socket = socket;
try {
this.output = this.socket.getOutputStream();
InputStream input = this.socket.getInputStream();
this.buffer = new ByteArrayOutputStream();
Thread connection = new Thread(this);
connection.start();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
IOUtils.output("[HANDLER] Connection from " + socket.getInetAddress());
while (connected()) {
byte[] bytes = this.buffer.toByteArray();
if (bytes.length < 8) return;
ByteBuffer buffer = ByteBuffer.wrap(bytes);
int size = buffer.getInt();
int id = buffer.getInt();
if (bytes.length < size + 8) continue;
byte[] data = Arrays.copyOfRange(bytes, 8, 8 + size);
this.processPacket(id, data);
this.buffer.close();
(this.buffer = new ByteArrayOutputStream()).write(bytes, 8 + size, bytes.length - 8 - size);
}
IOUtils.output("[HANDLER] Client ended connection - " + socket.getInetAddress());
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendPacket(int id, byte[] data) {
try {
ByteBuffer bytebuffer = ByteBuffer.allocate(8 + data.length);
bytebuffer.putInt(data.length);
bytebuffer.putInt(id);
bytebuffer.put(data);
byte[] bytes = bytebuffer.array();
this.output.write(bytes);
this.output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private void processPacket(int id, byte[] bytes) {
ByteBuffer data = ByteBuffer.wrap(bytes);
if (id == 0) {
IOUtils.output("Recieved packet with id 0");
} else if (id == 1) {
//TODO: authenticate user.
}
}
private boolean connected() {
return this.socket.isConnected() && !this.socket.isInputShutdown() && !this.socket.isOutputShutdown() && !this.socket.isClosed();
}
}
Server
public class Server implements Runnable {
private int port;
private ServerSocket sock;
public Server(int port) {
this.port = port;
launch();
}
private void launch() {
this.run();
}
#Override
public void run() {
try {
sock = new ServerSocket(port);
System.out.println("[SERVER] Server started");
while(!sock.isClosed()) {
new Handler(sock.accept());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I think this problem might be with ByteArrayOutputStream. I wanted to use ByteBuffer because I heard it was much faster than normal DataInput and output streams.
You are never calling Socket#read inside of your run method... If you dont read anything you dont have anything to work with in your loop, even when you are connected!
Take a look at this Tutorial about Sockets:
https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html
Your server code should use ServerSocket instead of Socket. Socket is used to represent Client Socket objects in Java.

Second client gets blocked when read from socket inputstream

I am sending a nonce to the client, however, the first client works fine. When the second client is running, it is blocked after server sent the encrypted nonce.
ReadByte Method:
private static void readByte(byte[] byteArray, InputStream byteIn, Socket socket) throws Exception{
int offset = 0;
int numRead = 0;
while (offset < byteArray.length && (numRead = byteIn.read(byteArray, offset, byteArray.length - offset)) >= 0){
offset += numRead;
}
if (offset < byteArray.length) {
System.out.println("File reception incomplete!");
}
}
EDIT ANSWER
Server:
public class Server2 {
private static final int NumberOfThreads = 5;
private static ExecutorService executorService =Executors.newScheduledThreadPool(NumberOfThreads);
private static final int port = 1111;
private static ServerSocket serverSocket;
private static final String privateKeyFile = "privateServer.der";
private static final String signedCert = "h.crt";
public static void main(String[] args) {
try{
serverSocket = new ServerSocket(port);
}catch (IOException e){
e.printStackTrace();
}
while(true){
System.out.println("Server is waiting for connection....");
try {
final Socket clientSocket = serverSocket.accept();
System.out.println("connection established....");
Runnable task = new Runnable() {
#Override
public void run() {
try {
handleClient(clientSocket);
}catch (Exception e){
e.printStackTrace();
}
}
};
executorService.execute(task);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void handleClient(Socket clientSocket) throws Exception{
//for getting the byte input and output
OutputStream byteOut = clientSocket.getOutputStream();
InputStream byteIn = clientSocket.getInputStream();
//for getting the string input and output
PrintWriter stringOut = new PrintWriter(clientSocket.getOutputStream(),true);
BufferedReader stringIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//print out client msg
System.out.println(stringIn.readLine());
stringOut.println("From Server: I am Server!");
stringOut.flush();
System.out.println("Sent to client: I am Server!");
//receive nonce from client
String nonceLen = stringIn.readLine();
byte[] nonce = new byte[Integer.parseInt(nonceLen)];
readByte(nonce,byteIn);
System.out.println("Nonce Received!");
//get private key from privateServer.der
PrivateKey privateKey = getPrivateKey();
//use private key to initialize the encryption mode
Cipher RSAEncrypt = Cipher.getInstance("RSA/ECB/PKCS1Padding");
RSAEncrypt.init(Cipher.ENCRYPT_MODE,privateKey);
//encrypt nonce and send it to the client
byte[] encryptedNonce = RSAEncrypt.doFinal(nonce);
stringOut.println(Integer.toString(encryptedNonce.length));
byteOut.write(encryptedNonce,0,encryptedNonce.length);
System.out.println(encryptedNonce);
byteOut.flush();
System.out.println("Sent to client: encrypted nonce");
}
}
Client:
public class Client2 {
private static final String server = "localhost";
private static final int port = 1111;
private static final String filePath = "medianFile.txt";
private static final String fileName = "medianFile.txt";
private static final String CAcert = "CA.crt";
public static void main(String[] args) {
try{
Socket socket = new Socket(server,port);
OutputStream byteOut = socket.getOutputStream();
InputStream byteIn = socket.getInputStream();
PrintWriter stringOut = new PrintWriter(socket.getOutputStream(),true);
BufferedReader stringIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stringOut.println("Please prove ur identity!");
stringOut.flush();
System.out.println("Sent to server: Please prove ur identity!");
String r1 = stringIn.readLine();
System.out.println(r1);
// send nonce
byte[] nonce = generateNonce();
if(r1.contains("I am server")){
stringOut.println(Integer.toString(nonce.length));
byteOut.write(nonce);
byteOut.flush();
System.out.println("Sent to server: nonce sent!");
}
// get encrypted nonce from server
String encryptedNonceLen = stringIn.readLine();
byte[] encryptedNonceBytes = new byte[Integer.parseInt(encryptedNonceLen)];
readByte(encryptedNonceBytes,byteIn,socket);
}
}

Simple Client-Server Program with NIO channels

SOLVED
If anyone would be interested I could edit this post with correct data. Just leave a comment.
As my assignment I had to create a simple server and a client using non-blocking channels and selectors.
Basically it should either echo the message written by the client or add two numbers(also provided by the client).
My problem is that I get errors at point where the message is about to be echoed by server.
I have checked if msg gets to writeResponse method, and it does. So that's where the problem starts.
Thank you all in advance !
Errors I get:
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:218)
at sun.nio.ch.IOUtil.read(IOUtil.java:191)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:359)
at SimpleServer.serviceRequest(SimpleServer.java:89)
at SimpleServer.serviceConnections(SimpleServer.java:61)
at SimpleServer.<init>(SimpleServer.java:35)
at SimpleServer.main(SimpleServer.java:141)
Server:
public class SimpleServer {
private ServerSocketChannel ssc = null; //for multiplexing
private Selector selector = null; //monitors channels
private static Charset charset = Charset.defaultCharset();//encoding
private static final int BSIZE = 1024;//buffer size
private ByteBuffer bbuf = ByteBuffer.allocate(BSIZE);
private StringBuffer reqString = new StringBuffer();
public SimpleServer(String host, int port) {
try {
ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.socket().bind(new InetSocketAddress(host, port));
selector = Selector.open(); //selector initiation
ssc.register(selector, SelectionKey.OP_ACCEPT); //registering communication channel
} catch(Exception exc) {
exc.printStackTrace();
System.out.println(1);
}
System.out.println("Server started and is ready for requests");
serviceConnections();
}//constructor
private void serviceConnections() {
boolean serverIsRunning = true;
while(serverIsRunning) {
try {
selector.select();//waits for answer from selector
Set<SelectionKey> keys = selector.selectedKeys(); //set of keys
Iterator<SelectionKey> iter = keys.iterator(); //iterration throught set of keys
while(iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next(); //obtain key
iter.remove(); //remove, because we'd get it again
if(key.isAcceptable()) {
SocketChannel cc = ssc.accept();//obtaining channel for communication
cc.configureBlocking(false);
cc.register(selector, SelectionKey.OP_READ); //registering selector for monitoring
continue;
}
if(key.isReadable()) { //channel with readable data
SocketChannel cc = (SocketChannel) key.channel();
serviceRequest(cc);
continue;
}
}//while loop
} catch(Exception exc) {
exc.printStackTrace();
continue;
}
}//outer while loop
}//serviceCconnection method
private void serviceRequest(SocketChannel sc) {
if(!sc.isOpen()) return;
reqString.setLength(0);
bbuf.clear();
try {
readLoop:
while (true) {
int n = sc.read(bbuf);
if(n > 0) {
bbuf.flip();//set limit, return to beginning
CharBuffer cbuf = charset.decode(bbuf);
while(cbuf.hasRemaining()) {
char c = cbuf.get();
if (c == '\r' || c == '\n') break readLoop;
reqString.append(c);
}
}
}//while loop
String[] req = reqString.toString().split(" ");
String cmd = req[0];
if (cmd.equals("bye")) {
sc.close();
sc.socket().close();
}
else if(cmd.equals("echo"))
writeResp(sc, reqString.toString());
else if(cmd.equals("add"))
writeResp(sc, Integer.parseInt(req[1]),Integer.parseInt( req[2]));
} catch (Exception exc) {
exc.printStackTrace();
try { sc.close();
sc.socket().close();
} catch (Exception e) {}
}
}//serviceRequest
//overloaded methods
public void writeResp(SocketChannel sc, String msg) throws IOException {
System.out.println(msg);
ByteBuffer cbuf = charset.encode(CharBuffer.wrap(msg));
cbuf = ByteBuffer.allocate(1024);
cbuf.put(msg.getBytes());
cbuf.rewind();
sc.write(cbuf);
}//writeResp method
public void writeResp(SocketChannel sc, int i, int j) throws IOException, NumberFormatException {
int ans = i + j;
String resp = Integer.toString(ans);
ByteBuffer cbuf = charset.encode(CharBuffer.wrap(resp));
sc.write(cbuf);
}//write Resp method
public static void main(String[] args) {
try {
String host = "localhost";
int port = 9998;
new SimpleServer(host, port);
} catch(Exception exc) {
exc.printStackTrace();
System.out.println(1);
}
}//main
}//class
My client:
public class SimpleClient {
private SocketChannel sc;
private static Charset charset;
private StringBuffer reqString = new StringBuffer();
private ByteBuffer bb;
String msg;
public SimpleClient(String host, int port) throws IOException, InterruptedException {
try {
sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(new InetSocketAddress(host, port));
System.out.println("Connecting to the server...");
while(!sc.finishConnect()) {
System.out.println("Connection is being established...");
}
} catch (IOException exc) {
System.out.println("IO exception");
System.exit(1);
}
System.out.println("Connection Established!");
makeRequest("echo Test input stream\n");
Thread.sleep(500);
readRequest();
}//constructor
private void makeRequest(String req) throws IOException {
System.out.println("Request: " + req);
bb = ByteBuffer.allocate(1024);
bb.put(req.getBytes());
bb.rewind();
sc.write(bb);
}//makeRequest method
public void readRequest() throws IOException, InterruptedException {
reqString.setLength(0);
bb.clear();
try {
readLoop:
while (true) {
bb.clear();
int readBytes = sc.read(bb);
if(readBytes == 0){
System.out.println("waiting for data");
continue;
}
else if(readBytes == -1) {
System.out.println("Server not responding");
break;
}
else {
bb.flip();
CharBuffer cbuf = charset.decode(bb);
while(cbuf.hasRemaining()) {
char c = cbuf.get();
if (c == '\r' || c == '\n') break readLoop;
reqString.append(c);
}
}
}//while loop
System.out.println(reqString.toString());
} catch( Exception exc) {//while loop
exc.printStackTrace();
}
}//readRequest method
public static void main(String[] args) {
try {
new SimpleClient("localhost", 9998);
}catch (IOException exc) {
exc.printStackTrace();
}catch(InterruptedException exc) {
exc.printStackTrace();
}
}//main method
}//class
If read() returns -1 it doesn't mean 'server not responding'. It means the peer has closed the connection, and you should do likewise. Instead you aren't closing it at all, so the operating system does a reset, so your server gets this exception.

Categories

Resources