Reputation: 2747
hi i am working on a client server programme with containing some special functions like sending private message, show online list etc. so i know i must use serialization and first i managed it but after a while a screwed up :) nowadays i spending time for learn to serialize. i will share only meaningfull parts for prevent comlpexity. and i wanna learn where i making wrong. so thanks for your help anyway. here is a part of server code;
public class Server {
private ServerSocket ss;
private Socket socket;
private Map<Socket,DataOutputStream> list = new HashMap<Socket,DataOutputStream>();
private LinkedList<Person> client_list = new LinkedList<Person>();
private String socketName;
private Object lockObj = new Object();
public Server(int port_number) throws IOException{
create_Server(port_number);
}
public static void main(String[] args) throws IOException {
int port_number=23;
new Server(port_number);
}
private void create_Server(int port_number) throws IOException{
ss = new ServerSocket(port_number);
System.out.println("Server is ready!");
while(true){
socket=ss.accept();
System.out.println(socket.getLocalAddress().getHostName() + " was connected!");
send_con_mes();
list.put(socket,new DataOutputStream(socket.getOutputStream()) );
ServerThread st = new ServerThread(socket,this);
Person per = new Person(socket.getInetAddress().toString());
client_list.add(per);
st.start();
}
}
public LinkedList<Person> send_list(){
return client_list;
}
so i am creating the server and waiting for response for any socket. moreover i used list for save the socket and its output and clien_list saves Object person (person is a serializable object ).
here is serverthread part
public class ServerThread extends Thread {
private Socket s;
private Server srv;
private String socketName;
private StringTokenizer str;
private String message = "";
private LinkedList<Person> client_list;
private ObjectOutputStream oos;
private static int i=0;
public ServerThread(Socket s,Server srv){
this.s = s;
this.srv = srv;
try {
oos = new ObjectOutputStream(s.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void setList(){
client_list = srv.send_list();
}
private LinkedList<Person> getList(){
return client_list;
}
@Override
public void run() {
String msg;
String token;
DataInputStream dis;
try {
dis = new DataInputStream(s.getInputStream());
while(true){
msg = dis.readUTF();
srv.send_to_All(msg, s);
setList();
oos.writeObject(getList());
oos.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
srv.remove_Connection(s);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
so i send client_list over on a ObjectOutputStream oos
to clients.
finally here is client part which takes the list and deserialize person object and read the information...
public class Client extends javax.swing.JFrame implements Runnable {
private DataOutputStream dos;
private DataInputStream dis;
private Socket s;
private String Client_name;
private String Ip_addr;
private Font font = new Font("Arial", Font.PLAIN, 13);
private int click_num_b=0;
private int click_num_i=0;
private LinkedList<Person> client_list;
private FileOutputStream fos;
private PrintStream pts;
private ObjectInputStream socketIn;
/** Creates new form Client */
public Client() {
initComponents();
Screen.setEditable(false);
Text_Field.setFont(font);
Screen.setFont(font);
start_Chat();
}
@Override
public void run() {
try {
while(true){
read_list();
String message = dis.readUTF();
Screen.append(message + "\n");
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void read_list() throws IOException{
socketIn = new ObjectInputStream(s.getInputStream());
try {
client_list = (LinkedList<Person>) socketIn.readObject();
for (Iterator<Person> itr = client_list.iterator(); itr.hasNext();) {
Person per = itr.next();
pts.println(per.getnickName() );
}
socketIn.close();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start_Chat() {
try {
Ip_addr = JOptionPane.showInputDialog("Enter the IP number of the server to connect : ");
s = new Socket(Ip_addr, 23);
Client_name = JOptionPane.showInputDialog("Enter your Nickname : ");
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
fos = new FileOutputStream("personList.txt");
pts = new PrintStream(fos);
new Thread(Client.this).start();
in here private ObjectInputStream socketIn;
takes the serializable object and writes on a file. here is some errors which i am facing with
java.io.EOFException
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at ServerThread.run(ServerThread.java:58)
SEVERE: null
java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at Client.read_list(Client.java:81)
at Client.run(Client.java:61)
at java.lang.Thread.run(Unknown Source)
so i appreciated if you can help me to handles this issue.
Upvotes: 1
Views: 2282
Reputation: 6907
You assume you 'must use serialization'. Serialization certainly is an option here, but certainly not the only option.
Serialization has a couple of disadvantages:
Using another encoding that was designed for client-server communication (JSON comes to mind) might be worth considering.
(I know it is annoying when you ask a question "how do I do foo with X" and people respond with "don't use X, use Y!", but it seems like you might want to consider this...)
Upvotes: 0
Reputation: 82589
Only ever send over your own objects. For example
interface ServerToClientPacket {
void performAction(Client c);
}
class MyMessage implements ServerToClientPacket {
String message;
MyMessage(String message) { this.message = message; }
void performAction(Client c) {
JOptionPane.showMessageDialog(message);
}
}
class PersonList implements ServerToClientPacket {
LinkedList<Person> people;
// constructor here
void performAction(Client c) {
for(Person person : people) {
c.pts.println(person);
}
}
}
Each will implement their own performAction on the client with the data that got serialized. When you define the behavior, instead of putting it in the client, put it in the message. Then your client becomes nothing more than a display mechanism for the various messages and behaviors passed to it from the socket.
Upvotes: 1
Reputation: 147164
It looks like you are using a stream and a decorated version of the same stream. Because there is some buffering going on, this wont work. Stick to using just the one decorated instance.
Upvotes: 1