由于需要序列化这个对象以便在网络上传输,所以POJO必须要实现java.io.Serializable接口。使用了
ObjectInputStream和ObjectOutputStream来接收和发送socket中的InputStream和OutputStream,然
后转换成Java对象。
client与server之间socket双向通信,因此要注意io读写的阻塞问题。client在写完数据时要记得
flush一下,然后再读数据,服务端从Socket的InputStream中读取数据的操作也是阻塞式的,如果
从输入流中没有读取到数据程序会一直在那里不动,直到客户端往Socket的输出流中写入了数据,
或关闭了Socket的输出流。
在读写object时用到了BufferedReader,下面是BufferedReader与InputReader区别
BufferedReader类
BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,而且提供了很实用的readLine,
读取一个文本行,从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
一般用法:
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ming.txt")));
String data = null;
while((data = br.readLine())!=null)
{
System.out.println(data);
}
InputStreamReader 类
是字节流通向字符流的桥梁,封裝了InputStream在里头, 它以较高级的方式,一次读取一个一个字符,以文本格
式输入 / 输出,可以指定编码格式;
一般用法:
InputStreamReader isr = new InputStreamReader(new FileInputStream("ming.txt"));
while((ch = isr.read())!=-1)
{
System.out.print((char)ch);
}
服务器端代码
public class server {
public static void main(String args[]) throws IOException{
//为了简单起见,所有的异常信息都往外抛
int port = 8899;
//定义一个ServerSocket监听在端口8899上
ServerSocket server = new ServerSocket(port);
while(true){
//server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
Socket socket=server.accept();
//每接收到一个Socket就建立一个新的线程来处理它
new Thread(new Task(socket)).start();
}
}
static class Task implements Runnable{
//静态内部类
private Socket socket;
public Task(Socket socket){
this.socket=socket;
}
@Override
public void run() {
ObjectInputStream oi = null;
ObjectOutputStream oo = null;
try{
handleSocket(oi,oo);
}
catch(Exception e){
e.printStackTrace();
}
finally{
try {
oi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
oo.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void handleSocket(ObjectInputStream oi,ObjectOutputStream oo) throws Exception{
//跟客户端建立好连接之后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了。
oi=new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
//获取obj
Object obj= oi.readObject();
ShopInfo shopInfo=(ShopInfo)obj;
System.out.println("from client: " + shopInfo.getShopName());
//获取输出流
oo=new ObjectOutputStream(socket.getOutputStream());
shopInfo.setShopName("东山再起");
//写对象
oo.writeObject(shopInfo);
//冲一下,从缓冲区写入
oo.flush();
}
}
}
客户端代码
public class client {
public static void main(String args[]) throws Exception {
//为了简单起见,所有的异常都直接往外抛
String host = "192.168.1.134"; //要连接的服务端IP地址
int port = 8899; //要连接的服务端对应的监听端口
//与服务端建立连接
Socket client = new Socket(host, port);
//建立连接后就可以往服务端写数据了
ObjectOutputStream os = new ObjectOutputStream(client.getOutputStream());
ShopInfo shopInfo=new ShopInfo();
shopInfo.setShopName("雷霆万钧");
os.writeObject(shopInfo);
os.flush();
ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(client.getInputStream()));
Object obj= is.readObject();
if(obj != null){
ShopInfo shop=(ShopInfo)obj;
System.out.println("from server: " + shop.getShopName());
}
is.close();
os.close();
client.close();
}
}
POJO实体
public class ShopInfo extends Serializable{
private static final long serialVersionUID = 1L;
/**
* 店铺名称
*/
private String shopName;
public void setShopName(String shopName){
this.shopName = shopName;
}
public String getShopName(){
return this.shopName;
}
}
运行结果如图
在有些情况下比如网络环境不好或者对象比较大的情况下需要把数据对象进行压缩然后在传输,此时就需要压缩这些
对象流,此时就可以GZIPInputStream和GZIPOutputStream来处理一下socket的InputStream和OutputStream。
仍然需要一个实现了java.io.Serializable接口的简单Java对象。下面为代码示例】
服务器端代码
public class server {
public static void main(String args[]) throws IOException{
//为了简单起见,所有的异常信息都往外抛
int port = 8899;
//定义一个ServerSocket监听在端口8899上
ServerSocket server = new ServerSocket(port);
while(true){
//server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的
Socket socket=server.accept();
//每接收到一个Socket就建立一个新的线程来处理它
new Thread(new Task(socket)).start();
}
}
static class Task implements Runnable{
//静态内部类
private Socket socket;
public Task(Socket socket){
this.socket=socket;
}
@Override
public void run() {
ObjectInputStream oi = null;
ObjectOutputStream oo = null;
try{
handleSocket(oi,oo);
}
catch(Exception e){
e.printStackTrace();
}
finally{
try {
oi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
oo.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void handleSocket(ObjectInputStream oi,ObjectOutputStream oo) throws Exception{
//跟客户端建立好连接之后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了。
//oi=new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
GZIPInputStream gzipos=new GZIPInputStream(socket.getInputStream());
oi=new ObjectInputStream(gzipos);
//获取obj
Object obj= oi.readObject();
ShopInfo shopInfo=(ShopInfo)obj;
System.out.println("from client: " + shopInfo.getShopName());
//获取输出流
oo=new ObjectOutputStream(socket.getOutputStream());
shopInfo.setShopName("东山再起");
//写对象
oo.writeObject(shopInfo);
//冲一下,从缓冲区写入
oo.flush();
}
}
}
客户端代码
public class client {
public static void main(String args[]) throws Exception {
//为了简单起见,所有的异常都直接往外抛
String host = "192.168.1.134"; //要连接的服务端IP地址
int port = 8899; //要连接的服务端对应的监听端口
//与服务端建立连接
Socket client = new Socket(host, port);
//建立连接后就可以往服务端写数据了
//ObjectOutputStream os = new ObjectOutputStream(client.getOutputStream());
GZIPOutputStream gzipos = new GZIPOutputStream(client.getOutputStream());
ObjectOutputStream os = new ObjectOutputStream(gzipos);
ShopInfo shopInfo=new ShopInfo();
shopInfo.setShopName("雷霆万钧");
os.writeObject(shopInfo);
os.flush();
gzipos.finish();
ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(client.getInputStream()));
Object obj= is.readObject();
if(obj != null){
ShopInfo shop=(ShopInfo)obj;
System.out.println("from server: " + shop.getShopName());
}
is.close();
os.close();
client.close();
}
}
使用加密协议传输对象
keytool -genkey -alias mysocket -keyalg RSA -keystore mysocket.jks
在提示输入项中,密码项自己给定,其它都不改直接回车,这里我使用的密码是“123123”。
运行Server
java -Djavax.net.ssl.keyStore=mysocket.jks -Djavax.net.ssl.keyStorePassword=123123 com.test.garbagecan.test.socket.ssl.MyServer
运行Client
java -Djavax.net.ssl.trustStore=mysocket.jks -Djavax.net.ssl.trustStorePassword=123123 com.test.garbagecan.test.socket.ssl.MyClient