最近在做个聊天的小项目,也比较忙,就没什么时间发博客了。今天早上是抽空出来发的,好吧,废话不多说。
由于做聊天这样的东西,肯定要用到socket、multyThread这类东西,而利用socket进行数据的传输无疑是必须的。java为我们提供了强大的IO流,利用socket,基本上可以传送任何类型的数据了。那么我在这里选择了ObjectOuputStream和ObjectInputStream,因为这两者可以传递对象。事不宜迟,先来个简单的对象传递的例子。
1、首先是一个简单的类,用于创建对象。
import java.io.Serializable;
public class User implements Serializable{ //实现序列号接口,但不需要实现任何方法
private String id;
private String name;
private String psw;
private String gender;
private String mail;
public User() {
super();
}
public User(String id, String name, String psw, String gender, String mail) {
super();
this.id = id;
this.name = name;
this.psw = psw;
this.gender = gender;
this.mail = mail;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getMail() {
return this.mail;
}
public String toString() {
return "User [gender=" + gender + ", id=" + id + ", mail=" + mail
+ ", name=" + name + ", psw=" + psw + "]";
}
}
2、接下来是客户端部分的代码
package test.socket;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
ObjectOutputStream oos = null;
InputStream is = null;
ObjectInputStream ois = null;
try {
socket = new Socket("localhost", 50000); //连接服务器
//获得输出流
os = socket.getOutputStream(); //客户端部分应该先初始化输出流
oos = new ObjectOutputStream(os);
//获得输入流
is = socket.getInputStream();
ois = new ObjectInputStream(new BufferedInputStream(is));
//初始化一个user对象,用于传递
User user = new User("10000", "小明", "123456", "男", "229047554@qq.com");
System.out.println("没送到服务器之前:" + user.toString());
//将user送往服务器端
oos.writeObject(user);
oos.flush();
//得到服务器送来的user
user = (User) ois.readObject();
System.out.println("送往服务器之后:" + user.toString());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(socket != null)
socket.close();
if(os != null)
os.close();
if(oos != null)
oos.close();
if(is != null)
is.close();
if(ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、接下来是服务器端代码
package test.socket;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.scau.model.User;
public class MyServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket clientSocket = null;
ObjectInputStream ois = null;
InputStream is = null;
OutputStream os = null;
ObjectOutputStream oos = null;
try {
serverSocket = new ServerSocket(50000);
while(true) {
clientSocket = serverSocket.accept();
//获得输入流
is = clientSocket.getInputStream(); //服务端部分应该先初始化输入流
ois = new ObjectInputStream(new BufferedInputStream(is));
//获得输出流
os = clientSocket.getOutputStream();
oos = new ObjectOutputStream(os);
User user = (User) ois.readObject();
user.setName("小红");
user.setGender("女");
oos.writeObject(user);
oos.flush();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if(serverSocket != null) {
serverSocket.close();
}
if(clientSocket != null)
clientSocket.close();
if(os != null)
os.close();
if(oos != null)
oos.close();
if(is != null)
is.close();
if(ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
其实代码是比较简单的。。。就不分析了,我也做了几点注释,在这里说说我遇到的几点问题吧。
1、客户端的代码在初始化对象流时,必须先初始化输出流,你可以将客户端的代码修改下,即把输出流放在输入流的下面然后在运行程序,你会发现,程序卡死了。其原因我也不是很清楚,但如果你一定要先初始化输入流,那也是可以的,那么你就在服务器端先初始化输出流,这样就没有问题了。
1、修正:其实只要两端都不先初始化输入流就行的,又重新实验了一下。
2、对于ObjectOutputStream和ObjectInputStream这两种流,是死锁流,也就是说在同一个线程里,你不能new 两个ObjectOutputStream或者两个ObjectInputStream出来,如果你这样做了,那么恭喜你,程序将会抛出异常java.net.SocketException: Connection reset或者卡死,反正各种问题。。。
3、对于多线程的socket,尤其是你需要保存socket,比如说:在做聊天功能的时候,你经常需要将socket保存到动态数组中ArrayList或者LinkedList,但是你又之前new了一个ObjectOutputStream,那么你再拿出这个socket进行传送数据时,你就不能再重新new一个ObjectOutputStream了,解决的方法有两个:第一,你可以再重新建立一个全新的socket,然后保存这个socket,这样你就可以new ObjectOutputStream了。第二:你也可以在保存socket的时候,将相应ObjectOutputStream对象保存下来,即也保存到一个动态数组中,这样需要使用的时候直接用就行了。。。
好吧,总结写到这里了,如有什么错误的地方,还请指正。联系:229047554@qq.com