基于I/O的Server/Client实现
在前面的文章中讲了基于NIO实现的Server/Client。本文就讲讲基于同步堵塞式I/O实现的Server/Client好与前面的NIO中的Server/Client进行对照。
网络编程中须要解决的两个主要问题:
1、怎样准确的定位网络上的一台或多台主机。
2、找到主机后怎样可靠高效的进行传输数据。
而解决这两个问题的主要方式就是非常好的运用TCP/IP协议。所以我们所做的网络编程都是基于TCP/IP来实现的。
基于Socket的java网络编程的通信过程:
server:使用ServerSocket监听它指定的port,等待client连接请求。client连接后,产生会话,在会话结束之后。关闭连接。
client:使用Socket对网络的某一服务的某一port发出连接请求。一旦连接成功。打开会话,会话完毕之后,关闭连接。
对一个功能齐全的Socket,都要包括下面的基本结构,当中过程包括下面四步:
1、创建Socket
2、打开连接到Socket的输入输出流
3、依照一定的协议对Socket进行读/写操作
4、关闭Socket
详细代码示比例如以下:
实现单线程
server端程序:
package IOSocket; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * server的工作就是在指定的端口上监听 * 建立连接 * 打开输出流 * 封装输出流 * 向client发送数据 * 关闭打开的输出流 * 关闭打开的Socket对象 * server端的程序,在while循环中所运行的动作 * 听。说,听,说... * @author Administrator * */ public class Server2 { private static final int port = 12345; public static void main(String[] args) { try { ServerSocket ss = new ServerSocket(port); //socket对象调用accept方法,等待请求的连接 System.out.println("server已启动,等待请求..."); Socket s = ss.accept(); //打开并封装输出流 DataOutputStream dos = new DataOutputStream(s.getOutputStream()); //打开并封装输入流 DataInputStream dis = new DataInputStream(s.getInputStream()); //封装并读取键盘上的输入流 BufferedReader br = new BufferedReader (new InputStreamReader(System.in)); String info; while(true){ //接收client发过来的信息 info = dis.readUTF(); System.out.println("client说:"+info); //假设发现对方说bye,则结束会话 if(info.equals("bye")){ break; } //读取键盘上的输入流,写入client info = br.readLine(); dos.writeUTF(info); //假设server自己说bye,也结束会话 if(info.equals("bye")){ break; } } dis.close(); dos.close(); s.close(); ss.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("网络连接异常,退出程序..."); } } }client程序:
package IOSocket; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.Socket; /** * 创建socket对象,指定server的ip地址和server监听的端口号 * client在new的时候,就发出了连接请求,server端就会进行处理 * client在while循环中运行操作: * 听,说,听,说... * */ public class Client2 { private final static String host = "localhost"; private final static int port = 12345; public static void main(String[] args) { try { Socket s = new Socket(host,port); System.out.println("client启动,发送请求..."); //打开并封装输出流 DataOutputStream dos = new DataOutputStream(s.getOutputStream()); //打开并封装输入流 DataInputStream dis = new DataInputStream(s.getInputStream()); //读取并封装键盘输入流 BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); String info; while(true){ //client先读取键盘输入信息 info = br.readLine(); //写入到server dos.writeUTF(info); //假设client自己说bye,即结束对话 if(info.equals("bye")){ break; } //接收server端信息 info = dis.readUTF(); System.out.println("server说: "+ info); if(info.equals("bye")){ break; } } dis.close(); dos.close(); s.close(); } catch (Exception e) { e.printStackTrace(); } } }
实现多线程
服务端程序:
package IOSocket; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class Server3 { private final static int port = 12345; public static void main(String[] args) { ServerSocket ss = null; Socket s = null; try { System.out.println("server端启动,等待..."); ss = new ServerSocket(port); s = ss.accept(); //打开并封装输出流 DataOutputStream dos = new DataOutputStream(s.getOutputStream()); //打开并封装输入流 DataInputStream dis = new DataInputStream(s.getInputStream()); new Thread(new MyServerReader(dis)).start(); new Thread(new MyServerWriter(dos)).start(); } catch (IOException e) { e.printStackTrace(); } } } //接受并打印client传过来的信息 class MyServerReader implements Runnable{ private DataInputStream dis; public MyServerReader(DataInputStream dis){ this.dis = dis; } @Override public void run() { String info; while(true){ //假设对方,即client没有说话,那么就会堵塞在这里 //可是这里的堵塞并不会影响其他的线程 try { info = dis.readUTF(); //假设状态由堵塞变为非堵塞,那么就答应接收到的信息 System.out.println("client说:"+info); if("bye".equals(info)){ System.out.println("退出程序!"); System.exit(0); } } catch (IOException e) { e.printStackTrace(); } } } } //从键盘获取输入流并写入信息到client class MyServerWriter implements Runnable{ private DataOutputStream dos; public MyServerWriter(DataOutputStream dos){ this.dos = dos; } @Override public void run() { //读取键盘上的输入流 InputStreamReader isr = new InputStreamReader(System.in); //封装键盘的输入流 BufferedReader br = new BufferedReader(isr); String info; while(true){ try { info = br.readLine(); dos.writeUTF(info); if("bye".equals(info)){ System.out.println("自己退出程序!"); System.exit(0); } } catch (IOException e) { e.printStackTrace(); } } } }client程序:
package IOSocket; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class Client3 { private final static String host = "localhost"; private final static int port = 12345; public static void main(String[] args) { Socket s = null; try { s = new Socket(host,port); System.out.println("client启动,发送消息..."); //打开并封装输入流 DataInputStream dis = new DataInputStream(s.getInputStream()); //打开并封装输出流 DataOutputStream dos = new DataOutputStream(s.getOutputStream()); new Thread(new MyClientReader(dis)).start(); new Thread(new MyClientWriter(dos)).start(); } catch (Exception e) { e.printStackTrace(); } } } //接收server端传过来的信息 class MyClientReader implements Runnable{ private DataInputStream dis; public MyClientReader(DataInputStream dis){ this.dis = dis; } @Override public void run() { String info; while(true){ try { info = dis.readUTF(); System.out.println("server说:"+info); if("bye".equals(info)){ System.out.println("对方下线,退出程序!"); System.exit(0); } } catch (IOException e) { e.printStackTrace(); } } } } //从键盘获得输入流并写入信息到服务端 class MyClientWriter implements Runnable{ private DataOutputStream dos; public MyClientWriter(DataOutputStream dos){ this.dos = dos; } @Override public void run() { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String info; while(true){ try { info = br.readLine(); dos.writeUTF(info); if("bye".equals(info)){ System.out.println("自己下线,退出程序!"); System.exit(0); } } catch (IOException e) { e.printStackTrace(); } } } }參考资料:http://www.cnblogs.com/hongten/archive/2012/04/29/java_socket.html