I have simple client and server, the client is based on NIO where as the server is a simple old style program.
I am using the client in its default mode which is blocking. In the program i try to write from the client side, server reads it. Then server replies and the client reads it.
I am able to write into the server with no issues, but the read from the Server in the client is proving to be problematic. As it is in blocking mode, i expect that it never returns 0 according to the documentation. But thats not what is happening, i always see the return from client_channel.read as 0.
*******************************SERVER*******************************************
class MyBlockingServer extends Thread
{
private int M_PortNumber;
private ServerSocket M_ServerSocket;
MyBlockingServer(int PortNumber)
{
M_PortNumber = PortNumber;
try {
M_ServerSocket = new ServerSocket(M_PortNumber);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run()
{
int my_number = 0;
while(true)
{
try {
Socket ClientServerTuple = M_ServerSocket.accept();
//System.out.println("Server address is "+ ClientServerTuple.getLocalAddress() + "Server Port is " + ClientServerTuple.getLocalPort());
//System.out.println("Client address is " + ClientServerTuple.getRemoteSocketAddress() + "Client address is" + ClientServerTuple.getPort());
DataInputStream inputStream = new DataInputStream(ClientServerTuple.getInputStream());
byte b[] = new byte[48];
inputStream.read(b);
System.out.println("[SERVER]" + new String(b));
DataOutputStream outputStream = new DataOutputStream(ClientServerTuple.getOutputStream());
byte c[] = new byte[100];
String output= new String("Thanks for connection, you suck tata" + " "+ my_number);
c = output.getBytes();
outputStream.write(c);
my_number++;
System.out.println("write done");
ClientServerTuple.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void socket_close()
{
try {
M_ServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class JavaBlocking
{
public static void main(String []args)
{
MyBlockingServer Server = new MyBlockingServer(8000);
try {
Server.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
*******************************CLIENT*******************************************
public class JavaChannels
{
public static void main(String []args)
{
SocketChannel client_channel = null;
try {
client_channel = SocketChannel.open();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("[Async Client] Socket channel open");
try {
client_channel.connect(new InetSocketAddress("127.0.0.1",8000));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("[Async Client] Socket channel connected");
ByteBuffer my_buffer = ByteBuffer.allocate(248);
try {
my_buffer.put("seven77".getBytes("UTF-8"));
} catch (UnsupportedEncodingException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
my_buffer.flip();
try {
int bytes_written = client_channel.write(my_buffer);
while(my_buffer.hasRemaining())
{
bytes_written = client_channel.write(my_buffer);
}
System.out.println("[Async Client] Wrote "+ bytes_written +" bytes");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("[Async Client] Socket channel write finished");
my_buffer.clear();
my_buffer.flip();
try {
int read_length = client_channel.read(my_buffer);
System.out.println("Initial read is " + read_length + " bytes");
while(read_length !=-1)
{
read_length = client_channel.read(my_buffer);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Reading the buffer." +"Read "+read_length +"bytes");
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("[Async Client] server says" + new String(my_buffer.array()));
try {
client_channel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The output i am seeing from the client side is as follows
Initial read is 0 bytes
Reading the buffer.Read 0bytes
Reading the buffer.Read 0bytes
Reading the buffer.Read 0bytes
I think that this is wrong:
System.out.println("[Async Client] Socket channel write finished");
my_buffer.clear();
my_buffer.flip();
The clear prepares the buffer for reading by setting the position to zero and the limit to the capacity.
But the flip then sets the limit to the position; i.e. zero. That means than when you attempt to read into the buffer, there is space for zero bytes.
Get rid of that flip call.
As it is in blocking mode, i expect that it never returns 0 according to the documentation.
Which documentation? The javadocs for SocketChannel.read(ByteBuffer) says:
"It is guaranteed, however, that if a channel is in blocking mode and there is at least one byte remaining in the buffer then this method will block until at least one byte is read. "
In this case, the highlighted condition is false.
Related
In my main thread I have a while(listening) loop which calls accept() on my ServerSocket object, then starts a new client thread and adds it to a Collection when a new client is accepted.
However, the accept() call in the while(listening) loop blocks and i'm struggling to close the connection. please find my below sample code, is there any way to create wrapper service to close the socket connection for the below server side program.
public static final void serverSocket(IData pipeline) throws ServiceException {
int clientNumber = 0;
ServerSocket listener = null;
int port =0;
Properties socketProperties = new Properties();
try
{
listener = new ServerSocket(port);
System.out.println(listener.getLocalSocketAddress());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
while(true){
new Connections(listener.accept(), clientNumber++).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
}
finally{
try {
listener.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static class Connections extends Thread {
private Socket socket;
private int clientNumber;
public Connections(Socket socket, int clientNumber) {
this.socket = socket;
this.clientNumber = clientNumber;
log("New connection with client# " + clientNumber + " at " + socket);
}
public void run()
{
try {
// Send a welcome message to the client.
while (true)
{
// my program
}
catch (IOException e) {
//exception
}
finally {
try {
socket.close();
}
catch (IOException e) {
log.error("Couldn't close a socket, what's going on?");
}
log("Connection with client# " + clientNumber + " closed");
}
}
Any suggestions would be much appreciated.
You have not adequately described the circumstances that dictate when you want to close.
In any case, your serverSocket object could become a static field that is made available to some other thread(s), and that other thread can decide when to close.
I am creating an application to Send a File from a Client and Receive it with a Server via Socket.
When I test the Application in my PC (Client-Server on same PC) everything runs Ok, but When I test the application on different PCs I've got the following errors.
First Attempt: Nothing happen, no errors, no file sent.
Second Attempt: Java throws an error of Ip already in use, but I receive the file on my Server PC but it has no data on it.
Here is the code for Client:
public class FileSender {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileSender nioClient = new FileSender();
SocketChannel socketChannel = nioClient.createChannel();
try {
nioClient.sendFile(socketChannel);
} catch (FileNotFoundException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//SocketChannel socketChannel = nioClient.createc
}
public SocketChannel createChannel(){
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open();
SocketAddress socketAddress = new InetSocketAddress("xx.xxx.xxx.x", 10002);
socketChannel.connect(socketAddress);
System.out.println("Connected..Now Sending the File");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return socketChannel;
}
public void sendFile(SocketChannel socketChannel) throws FileNotFoundException, InterruptedException{
RandomAccessFile afile = null;
try {
File file = new File("/home/dionisio/Imágenes/ImagenesOriginalesPrueba/flowers.jpg");
afile = new RandomAccessFile(file, "r");
FileChannel inChannel = afile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(8192);
while (inChannel.read(buffer) != -1) {
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
}
socketChannel.close();
afile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Server Code
public class FileReceiver {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileReceiver nioServer = new FileReceiver();
SocketChannel socketChannel = nioServer.createServerSocketChannel();
nioServer.readFileFromSocket(socketChannel);
}
private SocketChannel createServerSocketChannel() {
// TODO Auto-generated method stub
ServerSocketChannel serverSocketChannel = null;
SocketChannel socketChannel = null;
try {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(10002));
socketChannel = serverSocketChannel.accept();
System.out.println("Connection Stablished..."+socketChannel.getRemoteAddress());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return socketChannel;
}
private void readFileFromSocket(SocketChannel socketChannel) {
// TODO Auto-generated method stub
RandomAccessFile afile = null;
try {
afile = new RandomAccessFile("/home/dionisio/Imágenes/imagenesCopiaPrueba/flowersCopia.jpg","rw");
ByteBuffer buffer = ByteBuffer.allocate(8192);
FileChannel fileChannel = afile.getChannel();
while (socketChannel.read(buffer)>0) {
buffer.flip();
fileChannel.write(buffer);
buffer.clear();
}
Thread.sleep(1000);
fileChannel.close();
System.out.println("End of file reached...Closing Channel");
socketChannel.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Your read loops aren't correct. They should be of the form:
while (in.read(buffer) > 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
Otherwise you can lose data.
NB
Java does not throw an error 'IP already in use'. Be accurate.
You don't need the sleep. Don't add sleeps to networking code. It doesn't solve anything.
My folks thanks for your replies, now I know what was my error, I was putting the wrong Ip address on my client Application.
However EJP I will take your recommendation for a better byte check when writing on a Channel.
I have a Java Server and one(or more) Android Clients. For now I want them to communicate simply with strings. When i write from android I can get the data in Java Server, but when I try to get the answer from server the Android application stop working. The codes is reported below:
Java Server:
public class Server {
private static int port=12346, maxConnections=0;
// Listen for incoming connections and handle them
public static void main(String[] args) {
int i=0;
try{
ServerSocket listener = new ServerSocket(port);
Socket server;
while((i++ < maxConnections) || (maxConnections == 0)){
doComms connection;
server = listener.accept();
String end = server.getInetAddress().toString();
System.out.println("\n"+end+"\n");
doComms conn_c= new doComms(server);
Thread t = new Thread(conn_c);
t.start();
}
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}
class doComms implements Runnable {
private Socket server;
private String line,input;
public doComms(Socket server) {
this.server=server;
}
#SuppressWarnings("deprecation")
public void run () {
input="";
try {
// Get input from the client
DataInputStream in = new DataInputStream (server.getInputStream());
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(server.getOutputStream())),
true);
while((line = in.readLine()) != null && !line.equals(".")) {
input=input + line;
}
JOptionPane.showMessageDialog(null, input);
out.println("Enviado");
server.close();
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
And Android client's code (it's called every time a button is pressed inside onClick method):
public String enviaMensagem(){
String resposta="";
new Thread(new ClientThread()).start();
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket(ip, port);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(input.getText().toString());
resposta = dataInputStream.readUTF();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if (socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return resposta;
}
You are using an unsorted mixture of readUTF(), writeUTF(), readLine(), etc. They're not all interoperable. Settle on one of them. If you use writeUTF() you must use readUTF() at the other end. If you use readLine() you must write lines at the other end, with a line terminator such as \r\n or \n.
I am creating a desktop application in which multiple clients have to connect to the server using socket connection between them. I successfully connected them but the problem occurs when i connect multiple client simultaneously to the server, sever got an error "socket write error"
my code is below plz suggest me an answer..
public class SocketConnection implements Runnable {
// password of oracle database
ServerSocket serverSocket = null;
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
Socket clientSocket = null;
DBConnection dbConnection;
public SocketConnection() {
// TODO Auto-generated constructor stub
dbConnection = new DBConnection();
if (con != null) {
serverSocket = dbConnection.createSocket();
if (serverSocket != null) {
System.out.println("Server Started. Looking for the connections.");
System.out.println("Listening Port:8888.......");
}
Thread t = new Thread(this);
t.start();
}
}
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
clientSocket = serverSocket.accept();
System.out.println("Connection Accepted");
Connect m_connect = new Connect(clientSocket);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Connect implements Runnable {
Socket clientSocket = null;
Thread t = null;
private ResultSet res1;
private ResultSet res2;
Statement stmt;
private File mkFolder;
public Connect(Socket clientSocke) {
// TODO Auto-generated constructor stub
this.clientSocket = clientSocke;
try {
stmt = con.createStatement();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
t = new Thread(this);
t.start();
}
#Override
public void run() {
try {
dataInputStream = new DataInputStream(
clientSocket.getInputStream());
dataOutputStream = new DataOutputStream(
clientSocket.getOutputStream());
System.out.println("Connection established::"
+ clientSocket.getInetAddress());
String pass = dataInputStream.readUTF();
System.out.println(pass);
if (pass.equals("1")) {
//here is read n write operation
} else if (pass.equals("3")) {
//here is read n write operation
} else if (pass.equals("2")) {
//here is read n write operation
} else if (pass.equals("4")) {
//here is read n write operation
} else if (pass.equals("5")) {
//here is read n write operation
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Why you are doing this in that low-level way? Choose an well documented API and communicate through it!
Did you already read articles like this: Multithread client server chat on sockets. Load test. recv failed
Im trying to make a basic email system in Java. I have a server that the clients connect to and a gui for the clients. When the server picks up a new connection from a client it starts a new thread running that handles all the different operations. The problem is that the server accepts the new client but doesnt start a new client handler thread running. Any help?
public class Server {
public static Connection link;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
final int PORT = 1234; // Define the sockets and ports and i/o
Socket client;
ClientHandler handler;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
link = DriverManager.getConnection("jdbc:odbc:emails", "", "");
System.out.println("Connected to Database . . . ");
} catch (ClassNotFoundException cnfEx) {
System.out.println("* Unable to load driver! *");
System.exit(1);
} catch (SQLException sqlEx) {
System.out.println("* Cannot connect to database! *");
System.exit(1);
}
try {
serverSocket = new ServerSocket(PORT); // Set the server socket
} catch (IOException ioEx) {
System.out.println("\nUnable to set up port!"); // If failed let the
// user know
System.exit(1); // Exit the system with error code 1
}
System.out.println("\nServer running...\n"); // Tell the user the server
// is running
do {
client = serverSocket.accept();
// Wait for client.
System.out.println(client);
handler = new ClientHandler(client);
System.out.println(handler);
System.out.println("\nNew client accepted.\n"); // Tell the user the
// server has accepted
// a client
System.out.println("RUNNING");
handler.start(); // Start the handler
} while (true); // Continuous loop
}
static class ClientHandler extends Thread {
/**
*
*/
private Socket client;
private ObjectInputStream input; // Define sockets, i/o and local array
// list
private ObjectOutputStream output;
public ClientHandler(Socket socket) throws IOException // Client handler
// constructor
{
client = socket;
input = new ObjectInputStream(socket.getInputStream());// Set client
// and i/o
// stream
output = new ObjectOutputStream(socket.getOutputStream());
}
public void run() {
String userCommand = null;
System.out.println("RUNNING CLIENT HANDLER");
boolean quit = false;
do {
try {
userCommand = (String) input.readObject();
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (ClassNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} // Receive user command
if (userCommand.equals("SEND MESSAGE")) // If user command is to
// send a message
{
String username = null, recipient = null, message = null, insert, fileType = null;
try {
username = (String) input.readObject();
recipient = (String) input.readObject(); // Receive username,
// recipient and
// message
message = (String) input.readObject();
fileType = (String) input.readObject();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
insert = "INSERT INTO [emails] ([From], [To], [Message], [Attachment])"
+ " VALUES('"
+ username
+ "','"
+ recipient
+ "','"
+ message + "','" + fileType + "')";
Statement statement = null;
try {
statement = link.createStatement();
statement.executeUpdate(insert);
link.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
getFile(input, fileType);
} catch (IOException ioEx) {
ioEx.printStackTrace();
} catch (ClassNotFoundException cnfEx) {
cnfEx.printStackTrace();
}
System.out.println(username // Tell the user a message has been
// sent
+ " sent message to " + recipient);
}
if (userCommand.equals("READ MESSAGE")) // If user command is to
// read a message
{
String username = null; // Define local variables
try {
username = (String) input.readObject();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} // Receive the username of the current user
Statement statement = null;
String insert = "SELECT [Email No],[From],[Message],[Attachment] FROM [emails] WHERE To = '"
+ username + "'";
ResultSet rs = null;
try {
statement = link.createStatement();
rs = statement.executeQuery(insert);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
while (rs.next()) {
String from = rs.getString("From");
String message = rs.getString("Message");
String attachment = rs.getString("Attachment");
int emailNo = rs.getInt("Email no");
output.writeObject(from);
output.writeObject(message); // Send the username the
// message is from
output.writeObject(attachment);
output.writeObject(emailNo);
output.flush(); // and the message and flush the output
// stream
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
output.writeObject("END");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Send an end message
try {
output.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Flush the output stream
System.out.println(username // Tell the user someone is reading
// their messages
+ " reading messages.");
}
if (userCommand.equals("QUIT")) // If the user command is quit
{
quit = true; // Set quit to true
}
if (userCommand.equals("DELETE MESSAGE")) // If the user command is
// delete a message
{
int valueToDelete = 0; // Define local variables
try {
valueToDelete = Integer.parseInt((String) input.readObject());
} catch (NumberFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} // Receive the value to delete
Statement statement = null;
String delete = "DELETE FROM emails WHERE [Email No] = "
+ valueToDelete + "";
try {
statement = link.createStatement();
statement.executeUpdate(delete);
link.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Deleted message " + valueToDelete); // Tell
// the
// user a
// message
// has
// been
// deleted
}
} while (!quit); // Run while quit is false
System.out.println("Client Closed"); // Tell the user the client has // closed
}
private static void getFile(ObjectInputStream inStream, String fileType)
throws IOException, ClassNotFoundException {
byte[] byteArray = (byte[]) inStream.readObject();
FileOutputStream mediaStream = null;
if (fileType.equals("Text File"))
mediaStream = new FileOutputStream("file.txt");
else if (fileType.equals("Image"))
mediaStream = new FileOutputStream("file.gif");
else if (fileType.equals("Movie"))
mediaStream = new FileOutputStream("file.mpeg");
mediaStream.write(byteArray);
}
}
}
When you are instantiating the ObjectInputStream it will block until the client sends a sufficient header, thus you never get to actually run the thread... See also