I'm trying to implement a SCTP connection, everything works fine from the server's side but when I run the client program I get the following error:
java.net.ConnectException: Connection refused
at sun.nio.ch.SctpNet.connect0(Native Method)
at sun.nio.ch.SctpNet.connect(SctpNet.java:73)
at sun.nio.ch.SctpChannelImpl.connect(SctpChannelImpl.java:372)
at sun.nio.ch.SctpChannelImpl.connect(SctpChannelImpl.java:438)
at com.sun.nio.sctp.SctpChannel.open(SctpChannel.java:221)
at com.eska.sctp.client.SCTPClient.<init>(SCTPClient.java:20)
at com.eska.sctp.client.SCTPClient.main(SCTPClient.java:62)
The Server Code:
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import com.sun.nio.sctp.AbstractNotificationHandler;
import com.sun.nio.sctp.AssociationChangeNotification;
import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
import com.sun.nio.sctp.HandlerResult;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;
import com.sun.nio.sctp.ShutdownNotification;
public class SCTPServer {
private final static int SERVER_PORT = 1111;
private final static int BUFFER_SIZE = 1024;
private SctpServerChannel ssc;
public SCTPServer(int port) throws IOException {
this.ssc = SctpServerChannel.open();
// m.alkhader
// this.ssc.bind(new InetSocketAddress(port));
this.ssc.bind(new InetSocketAddress("127.0.0.1", port));
System.out.println("SCTP server started.");
System.out.println("Local addresses :");
Iterator iterator = this.ssc.getAllLocalAddresses().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
public void launch() throws IOException {
ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE);
CharBuffer cbuf = CharBuffer.allocate(BUFFER_SIZE);
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
while (true) {
System.out.println("Waiting for client connection...");
SctpChannel sc = this.ssc.accept();
System.out.println("Client connected");
System.out.println("Remote adresses :");
Iterator iterator = sc.getRemoteAddresses().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
AssociationHandler assocHandler = new AssociationHandler();
MessageInfo messageInfo = null;
do {
buf.clear();
cbuf.clear();
messageInfo = sc.receive(buf, null, assocHandler);
buf.flip();
messageInfo.unordered(true);
if (messageInfo != null && buf.limit() > 0) {
decoder.decode(buf, cbuf, true);
cbuf.flip();
System.out.print("Stream(" + messageInfo.streamNumber()
+ "):");
System.out.println(cbuf);
}
} while (messageInfo != null && buf.limit() > 0);
System.out.println("Connection closed by peer.");
}
}
public static void main(String[] args) {
try {
SCTPServer server = new SCTPServer(SERVER_PORT);
server.launch();
} catch (IOException e) {
System.out.println("Error : " + e.getMessage());
}
}
static class AssociationHandler extends AbstractNotificationHandler {
public HandlerResult handleNotification(
AssociationChangeNotification not, PrintStream stream) {
if (not.event().equals(AssocChangeEvent.COMM_UP)) {
int outbound = not.association().maxOutboundStreams();
int inbound = not.association().maxInboundStreams();
stream.printf("New association setup with %d outbound streams"
+ ", and %d inbound streams.\n", outbound, inbound);
}
return HandlerResult.CONTINUE;
}
public HandlerResult handleNotification(ShutdownNotification not,
PrintStream stream) {
stream.printf("The association has been shutdown.\n");
return HandlerResult.RETURN;
}
}
}
The Client Code:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Scanner;
import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;
public class SCTPClient {
private SctpChannel sc;
private final static int SERVER_PORT = 1111;
private final static int BUFFER_SIZE = 1024;
public SCTPClient(String addr, int port) throws IOException {
this.sc = SctpChannel.open(new InetSocketAddress(addr, port), 0, 0);
}
public void start() throws IOException {
MessageInfo messageInfo = MessageInfo.createOutgoing(null, 0);
Charset charset = Charset.forName("ISO-8859-1");
CharsetEncoder encoder = charset.newEncoder();
ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE);
CharBuffer cbuf = CharBuffer.allocate(BUFFER_SIZE);
Scanner scan = new Scanner(System.in);
int i = 0;
int max = this.sc.association().maxInboundStreams();
// messageInfo.unordered(true);
while (scan.hasNext()) {
buf.clear();
cbuf.clear();
cbuf.put(scan.nextLine());
cbuf.flip();
encoder.encode(cbuf, buf, true);
buf.flip();
messageInfo.streamNumber(i % max);
this.sc.send(buf, messageInfo);
i++;
}
}
public void stop() throws IOException {
this.sc.close();
}
public static void main(String[] args) {
try {
System.out.println("Client");
SCTPClient client = new SCTPClient("127.0.0.1", SERVER_PORT);
// SCTPClient client = new SCTPClient("192.168.0.1", SERVER_PORT);
System.out.println("Hello Client");
client.start();
client.stop();
} catch (IOException e) {
System.out.println("Error : " + e.getMessage());
e.printStackTrace();
}
}
}
everything works fine from the server's side
Related
I need to transfer a List between nodes and replace the existing one with the new one in the new node to achieve this, I'm using Sockets from Java.
I somehow have managed to transfer the data but only when I terminate the process. I need it to continue running, the process but at the same time transfer, the data in case any other new node joins the List.
How can I achieve this? I will have to introduce Threads in the Download along the road.
I got it working with files but now I need to change it to Sync lists, just having this is enough?
private static List<CloudByte> cloudByteList = Collections.synchronizedList(new ArrayList<>());
This is my current code:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static FileData.getCloudByteList;
import static FileData.getFile;
public class FileData {
private static File file;
private static String fileName;
private static List<CloudByte> cloudByteList = Collections.synchronizedList(new ArrayList<>());
public FileData(String fileName) throws IOException {
if (fileName == null) {
this.fileName = "data2.bin";
this.file = new File(this.fileName);
Download.downloadFile();
} else {
this.file = new File(fileName);
this.fileName = fileName;
fillingList();
}
}
public void fillingList() throws IOException {
byte[] fileContents = Files.readAllBytes(file.toPath());
for (int i = 0; i < fileContents.length - 1; i++) {
cloudByteList.add(new CloudByte(fileContents[i]));
}
}
public static List<CloudByte> getCloudByteList() {
return cloudByteList;
}
public static File getFile() {
return file;
}
public String getFileName() {
return fileName;
}
public static void setFile(File file) {
FileData.file = file;
}
/*--------------------------Download--------------------------*/
}
class Download extends Thread {
static ConnectingDirectory connectingDirectory;
#Override
public void run() {
try {
downloadFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void downloadFile() throws IOException {
var nodes = ConnectingDirectory.getNodes();
Socket socket = null;
if (getFile().exists()) {
System.out.println("File: " + getFile() + " exists.");
new Upload().uploadFile();
}
FileOutputStream fos = new FileOutputStream(FileData.getFile());
//ObjectOutputStream oos = new ObjectOutputStream(fos);
for (int i = 0; i < nodes.size() - 1; i++) {
if (!(nodes.get(i).getHostPort() == ConnectingDirectory.getHostIP())) {
System.out.println("test33123");
ServerSocket serverSocket = new ServerSocket(nodes.get(i).getHostPort());
System.out.println(serverSocket);
socket = serverSocket.accept();
System.out.println("now socket");
System.out.println(socket);
//socket = new Socket(nodes.get(i).getName(), nodes.get(i).getHostPort());
//System.out.println(socket);
int bytes = 0;
DataInputStream ois = new DataInputStream(socket.getInputStream());
long size = ois.readLong();
System.out.println(size);
byte[] buffer = new byte[100 * 10000];
while (size > 0 && (bytes = ois.read(buffer, 0, (int) Math.min(buffer.length, size))) != -1) {
System.out.println("test3333");
fos.write(buffer, 0, bytes);
size -= bytes;
}
}
}
}
}
/*--------------------------Upload--------------------------*/
class Upload {
public void uploadFile() throws IOException {
int bytes = 0;
var nodes = ConnectingDirectory.getNodes();
FileInputStream fileInputStream = new FileInputStream("data.bin");
DataInputStream ois = new DataInputStream(fileInputStream);
if (!getFile().exists()) {
System.out.println("File doesn't exist." + "\nDownloading the file!");
new Download().downloadFile();
}
System.out.println("hello");
for (int i = 0; i < nodes.size() - 1; i++) {
System.out.println("hello2");
Socket socket = new Socket(nodes.get(i).getName(), nodes.get(i).getHostPort());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeLong(new File("data.bin").length());
byte[] buffer = new byte[100 * 10000];
while ((bytes = ois.read(buffer)) != -1) {
dos.write(buffer, 0, bytes);
dos.flush();
}
}
}
}
As you can see, I'm using DataInput because if I try to use the ObjectInputStream, I get a Corrupted Header Exception. I have more classes to add to this. My goal is as I said, to transfer the data inside the "data.bin" to a "data2.bin" file. I'm able to create it and delete it but at the same time, no Data is being written/sent to it.
How can I fix the CorruptedHeaderException and get it to send the content?
All help is appreciated.
StorageNode Class:
import java.io.IOException;
import java.util.Scanner;
import java.util.regex.Pattern;
import static FileData.*;
public class StorageNode extends Thread {
private static int serverPort = 8080;
private static int clientPort = 8082;
private static String fileName = null;
private static String addressName = "localhost";
private static ConnectingDirectory connectingDirectory;
private static FileData fileData;
static ErrorInjection errorInjection;
public static void main(String[] args) throws IOException, InterruptedException {
/* if (args.length > 3) {
addressName = args[0];
serverPort = Integer.parseInt(args[1]);
clientPort = Integer.parseInt(args[2]);
fileData = new FileData(args[3]);
} else {
fileName = null;
fileData = new FileData(fileName);
}*/
connectingDirectory = new ConnectingDirectory(addressName, clientPort, serverPort);
fileData = new FileData(fileName);
errorInjection = new ErrorInjection();
errorInjection.start();
if(fileData.getFile().exists()){
new Upload().uploadFile();
}else {
new Download().downloadFile();
}
}
ConnectingDirectory Class
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class ConnectingDirectory {
private String hostName;
private static int hostIP;
private int directoryIP;
private InetAddress address;
private InputStream in;
private OutputStream out;
private static List<Nodes> nodes = new ArrayList<>();
List<String> nodess = new ArrayList<>();
private Socket socket;
private String sign = "INSC ";
public ConnectingDirectory(String hostName, int hostIP, int directoryIP) throws IOException {
this.hostName = hostName;
this.hostIP = hostIP;
this.directoryIP = directoryIP;
this.address = InetAddress.getByName(hostName);
this.socket = new Socket(address, directoryIP);
signUp();
askConnectedNodes();
}
public void signUp() throws IOException {
System.out.println("You are connecting to the following address: " + hostIP + "\n");
System.out.println("The port you are connected to: " + socket.getPort() + "\n");
in = socket.getInputStream();
out = socket.getOutputStream();
out.write(generateSignUp(address, hostIP).getBytes());
out.flush();
}
public String generateSignUp(InetAddress address, int hostIP) {
String signUpString = sign + address + " " + hostIP + "\n";
return signUpString;
}
public void askConnectedNodes() throws IOException {
String directoryNodesAvailable;
String a = "nodes\n";
out.write(a.getBytes());
out.flush();
Scanner scan = new Scanner(in);
while (true) {
directoryNodesAvailable = scan.nextLine();
addExistingNodes(directoryNodesAvailable);
//System.out.println("Eco: " + directoryNodesAvailable);
if (directoryNodesAvailable.equals("end")) {
out.flush();
printNodes();
break;
}
}
}
public void addExistingNodes(String sta) throws IOException {
if (sta.equals("end")) return;
if (!(nodess.contains(sta))) {
nodess.add(sta);
nodes.add(new Nodes(nodess.get(nodess.size() - 1)));
}
return;
}
public static List<Nodes> getNodes() {
return nodes;
}
public void printNodes() {
System.out.println("Checking for available nodes: \n");
nodes.forEach((z) -> System.out.println(z.getNode()));
}
public Socket getSocket() {
return socket;
}
public static int getHostIP() {
return hostIP;
}
public InetAddress getAddress() {
return address;
}
}
For all of those that need help in the future:
Sender side:
Socket socket = new Socket("localhost", hostPort);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ByteBlockRequest bbr = new ByteBlockRequest(getStoredData());
objectOutputStream.writeObject(bbr.blocksToSend(j));
Receiver side:
Socket = StorageNode.getServerSocket().accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
byte[] bit = (byte[]) ois.readObject();
In my case, I needed to use byte[], so I had to do a few additional functions in the back, to change Cloudbyte[] into byte[]. Once I did that, I was able to send the data using, ObjectInput/ObjectOutput.
I'm making a simple client-server rmi application with SSL. The code works fine, but when I copy a file that weights 58kb, it generates a copy that weights 1kb.
I'm going crazy with this. I will appreciate any help. This is the code:
Client:
package tpfinal;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import javax.rmi.ssl.SslRMIClientSocketFactory;
public class Client {
public static void main (String[] args) throws FileNotFoundException, IOException {
if (args.length < 2) {
System.out.println("Se necesitan dos argumentos: Hostname y Filename");
System.exit(1);
}
try {
System.setProperty("javax.net.ssl.keyStore","C:\\Users\\Lucho\\workspace\\Distribuida\\bin\\keystore");
System.setProperty("javax.net.ssl.keyStorePassword","123456");
System.setProperty("javax.net.ssl.trustStore","C:\\Users\\Lucho\\workspace\\Distribuida\\bin\\truststore");
System.setProperty("javax.net.ssl.trustStorePassword","123456");
Registry registry = LocateRegistry.getRegistry(null, ServerInterface.PORT, new SslRMIClientSocketFactory());
ServerInterface server = (ServerInterface) registry.lookup("SSLServer");
int bufferSize = 1024;
int pos = 0;
Respuesta respuesta = new Respuesta();
String serverPath = System.getProperty("user.dir") + System.getProperty("file.separator") + args[1];
String clientCopyPath = System.getProperty("user.dir") + System.getProperty("file.separator") + "clicopia1-" + args[1];
String serverCopyPath = System.getProperty("user.dir") + System.getProperty("file.separator") + "sercopia2-" + args[1];
System.out.println(serverPath + " serverPath");
System.out.println(clientCopyPath + " clientCopyPath");
respuesta = server.leerArchivo(serverPath, pos, bufferSize);
while (respuesta.getLeidos() > 0) {
if (server.escribirArchivo(clientCopyPath, respuesta.getLeidos(), respuesta.getBuffer()) == -1) {
System.out.println("Se produjo un error al abrir el archivo copia1");
}
if (server.escribirArchivo(serverCopyPath, respuesta.getLeidos(), respuesta.getBuffer()) == -1) {
System.out.println("Se produjo un error al abrir el archivo copia2");
}
pos += respuesta.getLeidos();
respuesta = server.leerArchivo(serverPath, pos, bufferSize);
System.out.println(pos);
}
if (respuesta.getLeidos() == -1) {
System.out.println("Se produjo un error al abrir el archivo original");
}
} catch (AccessException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
}
Server:
package tpfinal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
public class Server extends UnicastRemoteObject implements ServerInterface {
protected Server() throws RemoteException{
super(0, new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory(null, null, true));
}
public static void main(String[] args) {
try {
System.setProperty("javax.net.ssl.keyStore","C:\\Users\\Lucho\\workspace\\Distribuida\\bin\\keystore");
System.setProperty("javax.net.ssl.keyStorePassword","123456");
System.setProperty("javax.net.ssl.trustStore","C:\\Users\\Lucho\\workspace\\Distribuida\\bin\\truststore");
System.setProperty("javax.net.ssl.trustStorePassword","123456");
Registry registry = LocateRegistry.getRegistry(null, ServerInterface.PORT, new SslRMIClientSocketFactory());
Server server = new Server();
registry.rebind("SSLServer", server);
System.out.println("SSLServer bound in registry");
} catch (Exception e) {
System.out.println("SSLServer error: " + e.getMessage());
e.printStackTrace();
}
}
#Override
public Respuesta leerArchivo(String fileName, int pos, int cant)
throws RemoteException, FileNotFoundException, IOException {
File archivo = new File(fileName);
Respuesta respuesta = new Respuesta();
respuesta.setLeidos(-1);
respuesta.setPedidos(cant);
if (archivo.exists() && archivo.setReadOnly()) {
FileInputStream in = new FileInputStream(archivo);
in.skip(pos); // Descartamos lo leído.
respuesta.setLeidos(in.read(respuesta.getBuffer(), 0, cant));
if (respuesta.getLeidos() == -1) {
respuesta.setLeidos(0);
}
in.close();
}
return respuesta;
}
#Override
public int escribirArchivo(String fileName, int cant, byte[] data)
throws RemoteException, FileNotFoundException, IOException {
File archivo = new File(fileName);
FileOutputStream out = new FileOutputStream(archivo);
out.write(data, 0, cant);
out.close();
return cant;
}
}
RmiRegistry
package tpfinal;
import java.rmi.registry.LocateRegistry;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
public class RmiRegistry {
public static void main(String[] args) throws Exception {
System.out.println("Rmi Registry running on port " + ServerInterface.PORT);
System.setProperty("javax.net.ssl.keyStore","C:\\Users\\Lucho\\workspace\\Distribuida\\bin\\keystore");
System.setProperty("javax.net.ssl.keyStorePassword","123456");
System.setProperty("javax.net.ssl.trustStore","C:\\Users\\Lucho\\workspace\\Distribuida\\bin\\truststore");
System.setProperty("javax.net.ssl.trustStorePassword","123456");
LocateRegistry.createRegistry(ServerInterface.PORT,new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory(null, null, true));
//Sleep
Thread.sleep(Long.MAX_VALUE);
}
}
ServerInterface:
package tpfinal;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ServerInterface extends Remote {
int PORT = 8844;
public Respuesta leerArchivo(String fileName, int pos, int cant) throws RemoteException, FileNotFoundException, IOException;
public int escribirArchivo(String fileName, int cant, byte[] data) throws RemoteException, FileNotFoundException, IOException;
}
Response:
package tpfinal;
import java.io.Serializable;
public class Respuesta implements Serializable{
private static final long serialVersionId = 1L;
int pedidos;
int leidos;
byte[] buffer = new byte[1024];
public int getPedidos() {
return pedidos;
}
public void setPedidos(int pedidos) {
this.pedidos = pedidos;
}
public int getLeidos() {
return leidos;
}
public void setLeidos(int leidos) {
this.leidos = leidos;
}
public byte[] getBuffer() {
return buffer;
}
public void setBuffer(byte[] buffer) {
this.buffer = buffer;
}
}
The code works fine, but I'm not able to find this problem. If anyone want to try, you can remove the System.setProperty so you won't need to create keystore and truststore. Client must be executed like: java Client localhost nameOfAPicture for example: pic.jpg.
Every time you call escribirArchivos() you are creating a new file, rather than appending to it. So the file is always the size of the last write to it.
Difficult to see the point of reading a file from the server and then copying it back twice.
When I was learning NiO Java appeared bug. when the client disconnected, the server is not blocked.selector.select() always return 1
That‘s my code
package com.socket.Server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ImSocketServer {
private int port = 8888;
private Charset cs = Charset.forName("gbk");
private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
private Map<String, SocketChannel> clientsMap = new HashMap<String, SocketChannel>();
private static Selector selector;
public ImSocketServer(int port){
this.port = port;
try {
init();
} catch (Exception e) {
e.printStackTrace();
}
}
private void init() throws IOException{
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(new InetSocketAddress(port));
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("server start on port:"+port);
}
private void listen(){
while (true) {
try {
System.out.println(selector.select());
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for(SelectionKey key : selectionKeys){
try{
handle(key);
}
catch(Exception e){
System.out.println("挂了");
}
}
selectionKeys.clear();
selector.selectedKeys().clear();
} catch (Exception e) {
e.printStackTrace();
break;
}
}
}
private void handle(SelectionKey selectionKey) throws IOException {
ServerSocketChannel server = null;
SocketChannel client = null;
String receiveText=null;
int count=0;
if (selectionKey.isAcceptable()) {
server = (ServerSocketChannel) selectionKey.channel();
client = server.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) {
client = (SocketChannel) selectionKey.channel();
rBuffer.clear();
count = client.read(rBuffer);
if (count > 0) {
rBuffer.flip();
receiveText = String.valueOf(cs.decode(rBuffer).array());
System.out.println(client.toString()+":"+receiveText);
dispatch(client, receiveText);
client = (SocketChannel) selectionKey.channel();
client.register(selector, SelectionKey.OP_READ);
}
}
}
private void dispatch(SocketChannel client,String info) throws IOException{
Socket s = client.socket();
String name = "["+s.getInetAddress().toString().substring(1)+":"+Integer.toHexString(client.hashCode())+"]";
if(!clientsMap.isEmpty()){
for(Map.Entry<String, SocketChannel> entry : clientsMap.entrySet()){
SocketChannel temp = entry.getValue();
if(!client.equals(temp)){
sBuffer.clear();
sBuffer.put((name+":"+info).getBytes());
sBuffer.flip();
temp.write(sBuffer);
}
}
}
clientsMap.put(name, client);
}
public static void main(String[] args) throws IOException {
ImSocketServer server = new ImSocketServer(7777);
server.listen();
}
}
That makes sense. The socket channel is readable all the time and the read always returns EOF.
Once you read EOF from the channel, you need to remove it from the selector.
I've been playing around with sockets recently, but I've come across a problem...
I'm getting a "java.net.SocketException: socket closed" exception when I receive data from the server. I haven't closed the socket anywhere, in fact, the only place I use close() is on the scanner to read text from System.in;
Here is my code:
Client:
package packets.sidedcomputer;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import packets.MessagePacket;
import packets.sender.PacketSender;
import packets.side.Side;
public class Client extends SidedComputer
{
volatile boolean finished = false;
volatile String username;
volatile Server server;
public Socket clientSocket;
public ClientReciever reciever;
public Client(Server server, String username) throws UnknownHostException, IOException
{
this.username = username;
this.server = server;
this.reciever = new ClientReciever(this);
}
public void stopClient()
{
finished = true;
}
#Override
public void run()
{
Scanner scanner = new Scanner(System.in);
reciever.start();
while(!finished)
{
try
{
this.clientSocket = new Socket("192.168.1.25", 10501);
String line;
while((line = scanner.nextLine()) != null)
{
PacketSender sender = new PacketSender();
System.out.println("Client sending message \"" + line + "\" to server");
sender.sendPacket(new MessagePacket(line, username), clientSocket);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
scanner.close();
}
#Override
public Side getSide()
{
return Side.CLIENT;
}
}
Server:
package packets.sidedcomputer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import packets.Packet;
import packets.data.PacketData;
import packets.info.ClientInfo;
import packets.reciever.PacketReciever;
import packets.sender.PacketSender;
import packets.side.Side;
public class Server extends SidedComputer
{
volatile boolean finished = false;
public ServerSocket serverSocket;
public volatile List<ClientInfo> clients = new ArrayList<ClientInfo>();
public void stopServer()
{
finished = true;
}
public Server()
{
try
{
serverSocket = new ServerSocket(10501);
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public void run()
{
try
{
while (!finished)
{
Socket clientSocket = serverSocket.accept();
if(clientSocket != null)
{
ClientInfo clientInfo = new ClientInfo(clientSocket);
this.clients.add(clientInfo);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String dataString;
while((dataString = in.readLine()) != null)
{
PacketReciever packetReciever = new PacketReciever();
PacketData packetData = new PacketData();
packetData.decodeInto(dataString);
Packet packet = packetReciever.recievePacket(packetData, packetData.packetID, getSide(), clientSocket.getLocalAddress().getHostAddress().toString(), clientSocket.getLocalPort() + "");
PacketSender packetSender = new PacketSender();
for (ClientInfo client : this.clients)
{
PrintWriter out = new PrintWriter(client.socket.getOutputStream(), true);
packetSender.sendPacketToClient(packet, out);
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
#Override
public Side getSide()
{
return Side.SERVER;
}
}
Packet Sender:
package packets.sender;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import packets.Packet;
import packets.data.PacketData;
public class PacketSender implements IPacketSender
{
#Override
public void sendPacket(Packet packet, Socket socket)
{
if(packet.getDefualtID() == 0)
{
PacketData packetData = new PacketData(packet.getDefualtID());
packet.writeData(packetData);
String data = packetData.encodeIntoString();
sendData(socket, data);
}
}
protected void sendData(Socket socket, String data)
{
try
{
try
(
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
)
{
out.println(data);
}
catch (IOException e)
{
System.err.println("Couldn't get I/O for the connection to " + socket);
System.exit(1);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void sendPacketToClient(Packet packet, PrintWriter out)
{
PacketData packetData = new PacketData(packet.getDefualtID());
packet.writeData(packetData);
String data = packetData.encodeIntoString();
out.println(data);
}
}
Client Receiver:
package packets.sidedcomputer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import packets.data.PacketData;
import packets.reciever.PacketReciever;
import packets.side.Side;
public class ClientReciever extends Thread
{
public Client client;
public ClientReciever(Client client)
{
this.client = client;
}
volatile boolean running = true;
public void stopRunning()
{
running = false;
}
#Override
public void run()
{
while(running)
{
if(client.clientSocket != null)
{
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(client.clientSocket.getInputStream()));
String line;
while((line = in.readLine()) != null)
{
PacketReciever reciever = new PacketReciever();
PacketData packetData = new PacketData();
packetData.decodeInto(line);
reciever.recievePacket(packetData, packetData.packetID, Side.CLIENT, client.clientSocket.getLocalAddress().getHostAddress().toString(), client.clientSocket.getPort() + "");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
}
Packet Receiver:
package packets.reciever;
import packets.Packet;
import packets.MessagePacket;
import packets.data.PacketData;
import packets.side.Side;
public class PacketReciever implements IPacketReciever
{
#Override
public Packet recievePacket(PacketData packetData, int id, Side side, String hostName, String port)
{
Packet packet = null;
if(id == 0)
{
packet = new MessagePacket();
packet.readData(packetData);
packet.execute(side, hostName + ":" + port);
}
return packet;
}
}
I think the problem is your try-with-resources call in the sender, which will call close() at the end of the try block and hence close the Socket. Try using a single PrintWriter across all calls to sendData().
I have written code which helps my device to communicate using serial port. But after writing some lines the code sends the exception. And i do not know why it is doing this.
The code i have written is as under:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.SocketException;
import javax.comm.SerialPort;
import javax.comm.UnsupportedCommOperationException;
import org.dellroad.jvser.TelnetSerialPort;
import org.apache.commons.net.telnet.TelnetClient;
public class InclinometerCommunicator
{
private static final int DEFAULT_TCP_PORT = 10001;
private static final byte ADDRESS = (byte) 0xB1;
private static final byte ENQUIRY = 5;
private static final int PACKET_LENGTH = 11;
private TelnetSerialPort port;
public static final int BAUD_RATE = 9600;
public static final int DATA_BITS = SerialPort.DATABITS_8;
public static final int PARITY_BITS = SerialPort.PARITY_NONE;
public static final int STOP_BITS = SerialPort.STOPBITS_1;
public static final int FLOW_CONTROL = SerialPort.FLOWCONTROL_NONE;
public InclinometerCommunicator(InetAddress host) throws UnsupportedCommOperationException, SocketException, IOException {
this(host, DEFAULT_TCP_PORT);
}
public InclinometerCommunicator(InetAddress host, int tcpPort) throws UnsupportedCommOperationException, SocketException, IOException {
port = new TelnetSerialPort();
port.setSerialPortParams(BAUD_RATE, DATA_BITS, STOP_BITS, PARITY_BITS);
port.setFlowControlMode(FLOW_CONTROL);
port.setDTR(true);
port.setRTS(false);
port.getTelnetClient().connect(host, tcpPort);
}
public float getAngle() throws IOException, InterruptedException
{
sendFlowControl();
Thread.sleep(100);
sendEnquiry();
Thread.sleep(200);
receiveFlowControl();
Thread.sleep(200);
byte[] packet = readPacket();
return parsePacket(packet);
//return (float)1.5;
}
private void sendFlowControl() {
port.setDTR(false);
port.setRTS(true);
}
private void sendEnquiry() throws IOException {
OutputStream out = port.getOutputStream();
out.write(new byte[]{ADDRESS, ENQUIRY});
out.flush();
}
private void receiveFlowControl() {
port.setRTS(false);
port.setDTR(true);
}
private byte[] readPacket() throws IOException {
InputStream in = port.getInputStream();
byte[] buf = new byte[PACKET_LENGTH];
int totalRead = 0;
int i = 0;
while (totalRead < PACKET_LENGTH && i < 100) {
totalRead += in.read(buf, totalRead, PACKET_LENGTH - totalRead);
i++;
}
return buf;
}
private float parsePacket(byte[] packet) {
//TODO add additional checking
/*
for(byte b: packet)
System.out.print(b+" ");
System.out.print("\n");
*/
return (float) ((100*atoi(packet[1])) + (10*atoi(packet[2])) + atoi(packet[3]) + (.1*atoi(packet[5])) + (.01*atoi(packet[6])));
}
private int atoi(byte a) {
return (byte) (a - '0');
}
}
And the other class is here:
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
public class QService {
private InclinometerCommunicator communicator;
public static void main(String[] args) {
QService rc = new QService();
rc.run("10.168.217.106");
}
public void run(String ip)
{
try
{
communicator = new InclinometerCommunicator(InetAddress.getByName(ip), 9999);
}
catch (Exception e)
{
e.printStackTrace();
}
while (true)
{
float angle ;
try
{
angle = communicator.getAngle();
System.out.println("Angle:" + angle);
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println("Exception"+"::"+e); // Exception coming here
e.printStackTrace();
}
}
}
}
And the output is
Angle:-670.48
Angle:7118.36
Angle:367.57
Angle:7351.34
Angle:3094.42
Angle:-1599.83
Angle:527.55
Angle:7119.96
Angle:3857.8
Angle:209.53
Exception::java.net.SocketException: Software caused connection abort: socket write error
java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
at java.io.BufferedOutputStream.flush(Unknown Source)
at org.dellroad.jvser.telnet.TelnetClient._flushOutputStream(TelnetClient.java:81)
at org.dellroad.jvser.telnet.TelnetOutputStream.flush(TelnetOutputStream.java:146)
at InclinometerCommunicator.sendEnquiry(InclinometerCommunicator.java:66)
at InclinometerCommunicator.getAngle(InclinometerCommunicator.java:48)
at QService.run(QService.java:38)
at QService.main(QService.java:14)
This error is originating at the network layer, not the application layer. Looks like the underlying TCP connection is getting disconnected, perhaps due to the other side closing it unexpectedly. Check the logs on the other end. A tcpdump (or Wireshark) packet trace will verify what's going on at the TCP level.