zoukankan      html  css  js  c++  java
  • 基于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

  • 相关阅读:
    01前端-html
    2-3程序流程
    2-2视频缓存池
    2-1图像像素格式深度理解
    3.1.1 文件系统介绍
    3.1.4 文件属性
    CentOS开放端口的方法
    宝塔linux面板命令大全
    如何卸载Win10 RS3上预装的office2016
    win10家庭版升级专业版的两种方法和密钥
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6938279.html
Copyright © 2011-2022 走看看