I create program chat box, client will send code to server after that server will return object to client;
I use JFrame to create login.java. This frame will create new client and send this client to JFrame chatbox.java. chatbox will get data from server and server will get data from database.
database<--->server <---> client <---> JFrame.
But when I pass client from login.java to chatbox.java the server will create new socket. Then will make 2 socket run for 1 Jframe(wasted thread). How can I solve this problem or can you give me some ways to make this program! Thanks all
Code demo:
Server
public class Server {
public static void main(String[] args) {
int i = 1;
ExecutorService excutor = Executors.newFixedThreadPool(10);
UserDAO dao = new UserDAO();
try {
ServerSocket server = new ServerSocket(3333);
System.out.println("Server success");
while (true) {
Socket socket = server.accept();
System.out.println("connect success");
ThreadHandler thread = new ThreadHandler(socket);
excutor.execute(thread);
System.out.println("============");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
class ThreadHandler extends Thread {
UserDAO dao = new UserDAO();
private Socket socket;
private DataOutputStream dataOut;
private DataInputStream dataIn;
private ObjectInputStream objIn;
private ObjectOutputStream objOut;
private volatile boolean stop = false;
UserDAO userDAO;
User userSave ;
public ThreadHandler(Socket sockets) {
this.socket = sockets;
try {
dataOut = new DataOutputStream(socket.getOutputStream());
dataIn = new DataInputStream(socket.getInputStream());
objOut = new ObjectOutputStream(socket.getOutputStream());
objIn = new ObjectInputStream(socket.getInputStream());
userDAO = new UserDAO();
userSave = new User();
} catch (IOException e) {
System.out.println("error in constructor");
}
}
#Override
public void run() {
while (!stop) {
try {
String code = dataIn.readUTF();
switch (code) {
case "login":
try {
User user = (User) objIn.readObject();
this.userSave = user;
User userLogin = userDAO.loginUser(user);
objOut.writeObject(userLogin);
} catch (ClassNotFoundException e) {
System.out.println(e);
}
break;
} catch (IOException e) {
try {
userDAO.setStatusUser(false, userSave); //set account offline in db
dataIn.close();
objIn.close();
objOut.close();
} catch (IOException x) {
System.out.println(x);
}
break;
}
}
}
}
Client
public class Client {
DataOutputStream dataOut;
DataInputStream dataIn;
ObjectInputStream objIn;
ObjectOutputStream objOut;
Socket socket;
public Client() {
try {
socket = new Socket("localhost", 3333);
socket.setKeepAlive(true);
dataOut = new DataOutputStream(socket.getOutputStream());
objOut = new ObjectOutputStream(socket.getOutputStream());
objIn = new ObjectInputStream(socket.getInputStream());
dataIn = new DataInputStream(socket.getInputStream());
} catch (Exception e) {
System.out.println(e);
}
}
public User loginUser(User user) {
User fullUser = null;
try {
dataOut.writeUTF("login");
objOut.writeObject(user);
fullUser = (User) objIn.readObject();
} catch (IOException e) {
System.out.println(e);
} catch (ClassNotFoundException x) {
System.out.println(x);
}
return fullUser;
}
JFrame
public class Login extends javax.swing.JFrame {
Client client;
public Login() {
initComponents();
client = new Client();
this.setTitle("Login to TCS");
}
//bt login
private void btLoginActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String login = tfLogin.getText();
String password = String.copyValueOf(tfPassword.getPassword());
if(login.isEmpty()||password.isEmpty()){
JOptionPane.showMessageDialog(null,"Plz enter account!");
return;
}else{
User user = new User(login, password);
User userLogin = client.loginUser(user);
if(userLogin == null){
JOptionPane.showMessageDialog(null, "Your login or password is invalid!");
}else{
ListOfUser listOfUser = new ListOfUser(userLogin, client);//pass client to chatbox
listOfUser.setVisible(true);
this.dispose();
}
}
}
Related
I'm trying to send Message object from Server module to Client module. Unfortunately it throw java.io.StreamCorruptedException: invalid type code: 64 error. Does anyone know what is the problem with code below?
Client class from Server module
private boolean needToRun;
public final Socket socket;
private OutputStream outputStream;
private InputStream inputStream;
private ObjectOutputStream objOut;
private ObjectInputStream objIn;
public Client(Socket socket) {
this.needToRun = true;
this.socket = socket;
try {
this.outputStream = socket.getOutputStream();
this.inputStream = socket.getInputStream();
this.objOut = new ObjectOutputStream(outputStream);
this.objIn = new ObjectInputStream(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
run();
}
public void send(Message msg) {
try {
objOut.writeObject(msg);
objOut.flush();
objOut.reset();
} catch (Exception ex){
ex.printStackTrace();
}
}
public void close() {
needToRun = false;
}
public void run() {
new Thread(() -> {
while(needToRun) {
try {
int amount = inputStream.available();
if (amount != 0) {
Message msg = (Message) objIn.readObject();
receivedContent(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public void receivedContent(Message msg) {
for (Client connection : Server.clients) {
connection.send(msg);
}
}
the Client class from Client module looks the same but receivedContent looks like this:
public void receivedContent(Message msg) {
String errorName = msg.content().trim();
MainPane.addLabel(errorName);
}
and last one Server class, which accepts socket connections:
while (true) {
System.out.println("running");
try {
System.out.println("Waiting for client...");
Socket socket = serverSocket.accept();
clients.add(new Client(socket));
} catch (Exception e) {
if (!serverSocket.isClosed()) {
stopServer();
}
break;
}
}
I have a Server project and a Client project. While the Server is running the first connection from client works fine. At the seccond connection the Server fires the "java.net.BindException: Address already in use: JVM_Bind " error. Is there a way to add more connections on the same port?
Server:
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Socket pipe = null;
while(true){
ServerSocket s = new ServerSocket(2345);
pipe = s.accept();
Connection c = new Connection(pipe);
c.start();
}
}
}
public class Connection extends Thread{
private Socket socket = null;
Mensch jim = null;
ObjectInputStream input = null;
ObjectOutputStream output = null;
ServerSocket s = null;
public Connection(Socket s){
socket = s;
}
public void run(){
try {
input = new ObjectInputStream(socket.getInputStream());
output = new ObjectOutputStream(socket.getOutputStream());
jim = (Mensch) input.readObject();
jim.setAge(33);
output.writeObject(jim);
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
And the Client:
public class Main {
public static void main(String[] args) {
Mensch jim = new Mensch(19, "Jim");
System.out.println(jim.getAge());
try {
Socket s = new Socket("127.0.0.1", 2345);
ObjectOutputStream clientOutputStream = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream clientInputStream = new ObjectInputStream(s.getInputStream());
clientOutputStream.writeObject(jim);
jim = (Mensch) clientInputStream.readObject();
System.out.println(jim.getAge());
clientOutputStream.close();
clientInputStream.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the problem:
while(true) {
ServerSocket s = new ServerSocket(2345);
pipe = s.accept();
...
}
You're trying to bind to the same port repeatedly. All you need to do is create a single ServerSocket and call accept on it multiple times. (I'd also move the pipe variable declaration inside the loop...)
ServerSocket s = new ServerSocket(2345);
while(true) {
Socket pipe = s.accept();
...
}
So I have seen a lot of different questions like this but no definitive help, at least to my understanding or my personal application. I am making a socket "chat room" program that allows the user to send images to selected users through a central server. I can establish the clients to connect but when sending an image this error occurs. Here is my code:
Client:
Thread thread = new Thread() {
#Override
public void run() {
try {
s = new Socket("localhost", 4000);
while (s.isConnected()) {
oos = new ObjectOutputStream(s.getOutputStream());
if (!initialized) {
oos.writeObject(identity);
oos.flush();
oos.reset();
initialized = true;
}
baos = new ByteArrayOutputStream(1000);
// Take screenshot
BufferedImage img = new Robot()
.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
// Write img to baos
ImageIO.write(img, "jpg", baos);
// Send image over socket
oos.writeObject(baos.toByteArray());
oos.flush();
oos.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
Central Server Home:
public Home() {
initComponents();
textView = new Terminal(terminal);
users = new CopyOnWriteArrayList<>();
Thread startServer = new Thread(new ServerStart());
startServer.start();
}
public class ServerStart implements Runnable {
#Override
public void run() {
try {
serverSock = new ServerSocket(4000);
terminal.append("Server started...\n");
while (true) {
// Detect client connection
Socket clientSock = serverSock.accept();
Thread thread = new Thread(new ClientHandler(clientSock));
thread.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public class ClientHandler implements Runnable {
Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
User user = new User(socket);
terminal.append(user.getName() + " connected as " + user.getType() + "...\n");
if (user.getType().equals(User.TYPE_01)) {
users.add(user);
} else {
User client = findUser(user);
while(true){
user.sendScreen(client.receiveScreen());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private User findUser(User user) {
for (User client : users) {
if (client.getCompany().equals(user.getCompany())) {
if (client.getName().equals(user.getName())) {
return client;
}
}
}
return null;
}
}
Central Server User:
public static final String TYPE_00 = "VIEWER";
public static final String TYPE_01 = "CLIENT";
private byte[] bytes;
private ObjectInputStream in;
private ObjectOutputStream out;
private String company, name, type;
public User(Socket socket) throws IOException {
this.out = new ObjectOutputStream(socket.getOutputStream());
this.in = new ObjectInputStream(socket.getInputStream());
setUserType();
}
public void sendScreen(byte[] bytes) {
try {
out.writeObject(bytes);
out.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public byte[] receiveScreen() {
byte[] bytes = null;
try {
bytes = (byte[]) in.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return bytes;
}
public String getCompany() {
return company;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public void setUserType()
{
String[] strings = null;
try{
strings = (String[])in.readObject();
type = strings[0];
company = strings[1];
name = strings[2];
} catch(Exception e){
e.printStackTrace();
}
}
Client Viewer:
Thread thread = new Thread() {
#Override
public void run() {
try {
Socket s = new Socket("localhost",4000);
String[] strings = { TYPE, "Vision", "cadams" };
while (s.isConnected()) {
if(!initialized){
System.out.println("initialized");
oos = new ObjectOutputStream(s.getOutputStream());
oos.writeObject(strings);
oos.flush();
oos.reset();
initialized = true;
}
ois = new ObjectInputStream(s.getInputStream());
byte[] bytes = (byte[]) ois.readObject();
BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIcon ico = new ImageIcon(
img.getScaledInstance(viewer.getWidth(), viewer.getHeight(), Image.SCALE_SMOOTH));
viewer.setIcon(ico);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
}
I have done some extensive research and know that this could be from my streams looking like a bowl of ramen noodles but I haven't seen any sort of proposal on how to fix it in terms of source. I thank those who can contribute and please let me know if there is anything I can do to further understanding.
Don't keep creating new ObjectInput/OutputStreams. Use the same ones for the life of the socket.
NB while (s.isConnected() isn't valid. It doesn't magically become false when the peer disconnects. You need to handle end of stream and the various socket termination exceptions.
Right now my server only can handle one client at a time. I am trying to use a Thread so that the server can handle several clients, but I am doing it wrong. I have added the thread in the try/catch clause where the serverSocket accepts the client, but this makes no difference. I don't get an error or anything, but it just doesn't work.
So what I want to do, is make the server not freeze at one client, but still accept several clients.
Here is the server code:
import java.io.*;
import java.net.*;
public class Server {
private BufferedReader reader;
private PrintWriter writer;
private int port;
public Server(int port)
{
this.port = port;
}
private String getSeverAddress() {
String host = null;
try {
InetAddress adr = InetAddress.getLocalHost();
host = adr.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return host;
}
public void startServer() {
print("Contact this sever on address: " + getSeverAddress() + " port: " + port);
ServerSocket ss = null;
Socket socket = null;
Thread clientThread = null;
try {
ss = new ServerSocket(port);
socket = ss.accept();
clientThread = new Thread(new Client(socket));
clientThread.start();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(socket.getOutputStream(), true);
String msg = null;
while (( msg = reader.readLine()) != null) {
print("System out: " + msg);
if(msg.equals("Bye")) {
print("Client left");
break;
}
}
ss.close();
socket.close();
reader.close();
writer.close();
} catch(SocketException e) {
e.printStackTrace();
} catch (IOException i ) {
i.printStackTrace();
return;
}
}
private void print(String msg) {
System.out.println(msg);
}
public static void main(String[] args) {
Server server = new Server(1111);
server.startServer();
}
}
Here is the client code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client implements Runnable{
private Socket client;
private BufferedReader reader;
private PrintWriter writer;
public Client(Socket socket)
{
client = socket;
try{
reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
writer = new PrintWriter(client.getOutputStream(), true);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
#Override
public void run() {
String msg = null;
BufferedReader r = null;
try {
r = new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println("Write message to server");
while(true) {
try {
msg = r.readLine();
if(msg.equals("Quit") || msg == null) {
print("Disconnect");
break;
}
} catch (IOException e) {
e.printStackTrace();
}
writeToServer(msg);
}
try {
r.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeToServer(String msg) {
writer.println(msg);
}
private void print(String msg) {
System.out.println(msg);
}
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("localhost", 1111);
} catch (Exception e) {
e.printStackTrace();
}
Client client = new Client(socket);
client.run();
}
}
You are still trying to handle clients in your main thread. Main thread should just accept new connections and start new threads. You also have to do accept in a loop so multiple connections can be accepted:
ss = new ServerSocket(port);
while(true) {
Socket socket = ss.accept();
Thread clientThread = new Thread(new Runnable() {
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
String msg = null;
while (( msg = reader.readLine()) != null) {
print("System out: " + msg);
if(msg.equals("Bye")) {
print("Client left");
break;
}
}
socket.close();
reader.close();
writer.close();
}});
clientThread.start();
}
You need to put your ss.accept() into a while loop and create a new Thread for every client accepted, which handles the connection.
Problem:
I have written one java socket server which send response when I send first message from the client to it. But I want to send one more message based on the first response. After the first response i am not getting any other response?
Here is the Server code:
public class SendSmsServerSocket {
private final static CxpsLogger logger = CxpsLogger.getLogger(SendSmsServerSocket.class);
SendSmsServerSocket(){
try {
new SeverSocketForSms(new ServerSocket(4330));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class SeverSocketForSms extends Thread {
private Socket socket;
private ServerSocket serversocket;
private volatile static boolean running = true;
public SeverSocketForSms(ServerSocket ssocket) throws IOException {
this.serversocket = ssocket;
start();
}
public void run() {
try{
while(running) {
this.socket = serversocket.accept();
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : "+msg);
}
}
catch(Exception e){
e.printStackTrace();
}
catch(Throwable t) {
System.out.println("Caught " + t + "xmlServerThread - closing thread");
}
}
public static void shutdown() {
System.out.println("Stopping socket connection and thread");
try{
socket.close();
}catch (Exception e) {
e.printStackTrace();
}
running = false;
}
public static void main (String [] args){
try {
System.out.println("Starting sms server ----- Please press Enter Key to stop the server after receiving one message");
SendSmsServerSocket s=new SendSmsServerSocket();
new Scanner(System.in).nextLine();
SeverSocketForSms.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Once you have an incoming connection, you should delgate the responsibility for handling that incoming connection to another Thread, otherwise you will block your "accept" thread until the current connection is closed...
while (running) {
this.socket = serversocket.accept();
Thread thread = new Thread(new Handler(socket));
thread.start();
}
And the Handler
public class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket){
this.socket = socket;
}
public void run() {
// You may need to add a repeat and exit clause here...
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : " + msg);
}
}