Java实现基础的client/server模型

java对网络的支持
1、java支持基于 流的通信(Stream-based communication),也支持 基于包的通信(backage-based communication)
2、 基于流的通信使用 TCP协议(传输控制协议), 基于包的通信使用 UDP协议(用户数据报协议)
3、相对于UDP协议,TCP协议能发现丢失的传输信息并且重新发送, 因此大多数java程序采用基于流的通信;

客户端/服务器数据交流
1、Java API提供用于创建套接字的类以用于程序的网络通信;
套接字(Socket)是两台主机之间的逻辑连接的端点,可以用来发送和接收数据;
2、示例代码:
 
 <span style="color:#000000;">import java.net.*;
  import java.io.*;、
 
  class Server{
           int port = 8000;   //端口
           try{
                 ServerSocket server = new ServerSocket(port);   //创建服务器套接字
                 Socket socket = server.accept();                //创建套接字监听器
 
                InputStream input = new InputStream(socket.getInputStream());     //创建服务器输入输出流
                 OutputStream output = new OutputStream(socket.getOutputStream());
 
                 //以下代码可以加入到一个while(true)块中,以实现客户端服务器之间不间断的数据交流
                 System.out.println(input.read());   //服务器从输入流中读取数据
                 output.write(aNumber);      //服务器向输出流写入数据
           }
           catch(IOException e){         //由于输入输出流的存在,可能抛出IOException异常
                 System.err.println(e);
           }
  }
 
  class Client{
           int port = 8000;      //端口
           String host = "localHost";     //服务器主机名,localHost=127.0.0.1
           try{
                 Socket socket = new Socket(host,port);
                
                 InputStream input = new InputStream(socket.getInputStream());
                OutputStream output = new OutputStream(socket.getOutputStream());
                
                 System.out.println(input.read());  
                 output.write(aNumber);     
           }
           catch(IOException e){
                 System.err.println(e);
           }
  }</span>


※如果客户端服务器模型使用GUI构建的话,那么框架构建的代码要放在建立套接字连接的try/catch块之前,否知会引起线程阻塞,而无法显示GUI;

30.2 一个服务端对应多个客户端
1、单个服务端对应多个客户端:将各个客户端包装为线程,使用多线程交换数据流
  ServerSocket socket = new ServerSocket(port);
  while(true){                   //while(true)块能使服务端不停地获取新连接的客户端的套接字
           Socket socket = serverSocket.accpet();
           Thread thread = new ThreadClass(socket);
           thread.start();
  }


或者使用线程池(更方便对各个线程的客户端进行管理):
 
<span style="color:#000000;">ServerSocket server = new ServerSocket(port);
  ExecutorService executor = Executors.newCachedPool();
  while(true){                   //while(true)块能使服务端不停地获取新连接的客户端的套接字
             Socket socket = service.accept();
             executor.execute(socket);
  }</span>


 2、示例代码:
 
<span style="color:#000000;">import java.io.*;
  import java.net.*;
 
  class Server{
           int port = 8000;
           try{
                 ServerSocket server = new ServerSocket(port);
                 while(true){
                       Socket socket = server.accept();
                       Thread thread = new ThreadClass(socket);
                       thread.start();
                 }
           }
           catch(IOException e){
                 System.err.println(e);
           }
  }
 
  class ThreadClass{
           private Socket socket ;
           ThreadClass(socket){
                 this.socket = socket;
           }
           public void run(){
                 try{
                       InputStream input = new InputStream(socket.getInputStream());
                      OutputStream output = new OutPutStream(socket.getOutputStream());
 
                       System.out.println(input.read());   //服务器从输入流中读取数据
                       output.write(aNumber);      //服务器向输出流写入数据
                 }
                 catch(IOException e){
                       System.err.println(e);
                 }
           }
  }</span>


 ※可以通过以下的方法对各个客户端的输入输出流进行控制(所有用户数据共享,通过限制线程数限制客户端数量等)
 
 class JFrame{
             List<Socket> list = new List<Socket>();  //记录所有客户端的套接字
             static void main(){
                    new JFrame();
             }
             JFrame(){
                 //在try块之前,要完成主框架的构建,否则会陷入线程阻塞
                    try{
                          ExecutorService executor = Executors.newCachedPool();
                           while(true){             //while(true)块可以使服务器不停地获取新的客户端套接字
                                 Socket socket = service.accept();
                                 executor.execute(new Task(socket));
                                 list.add(socket);
                          }
                    }
             }
           
             class Task() implements Runnable{
                    Socket socket;
                    Task(){  }
                    void run(){
                          try{
                                 while(true){    //while(true)块使服务器客户端能持续地交换数据
                                        InputStream in = new InputStream(socket.getInputStream());
                                        input.read();                            //从该个客户端读取数据流
                                        for(Socket socket:list){
                                               OutputStream out = new OutputSteam(socket.getOutputStream());
                                               out.write();         //向每一个客户端写入数据流
                                        }
                                 }
                          }
                          catch(IOException)
                         
                    }
             }
  }




30.3 InetAddress类:获取主机名、IP地址
 1、从Socket套接字监听器类中获取
<span style="color:#000000;"> Socket socket = new Socket(host,port);  //Socket socket = (new ServerSocket(port)).accept();
  InetAddress inetAddress = socket.getInetAddress();
  inetAddress.getHostName();             //获取主机名
  inerAddress.getHostAddress();          //获取主机IP地址</span>


  2、直接从主机名或IP地址构建
 
<span style="color:#000000;"> InetAddress inetAddress = InetAddress.getByName("hostName");
  InetAddress inetAddress = InetAddress.getByName("HostIPAddress");</span>


30.4 applet 服务端
applet客户端:可以使用getCodeBase().getHost()以获取服务器的主机名,applet程序架设在服务端上面;  
 application:Socket socket = new Socket("localhost",8000);
 applet:Socket socket = new Socket(getCodeBase().getHost(),8000);

30.5 发送和接收对象
可以在套接字Socket字流上使用 ObjectOutputStream和ObjectInputStream来发送和接收对象;

30.6 从Web服务器上读取文件
1、使用 URL的openStream方法对URL定位的文件加载到字流并读取;
2、模型:
void main(){
           try{
                 URL url = new URL(urlString:String);
                 Scanner input = new Scanner(url.openStream());
                 while(input.hasNext()){
                       System.out.println(input.nextLine());
                }
           }
           /*try{
                 URL url = new URL(urlString);
                 BufferedReader input = new BufferedReader(new InputStreamReader(url.openStream());
                 String str = "";
                 while((str=input.readLine()) != null){
                       System.out.println(str);
                 }
           }   //
 
           catch(MalformedURLException e){   //URL格式错误抛出的异常
                 System.out.println(e.getMessage());
           }
           catch(IOException e){
                 System.out.println(e.getMessage());
           }
           finally{
                 input.close();
           }
  }



30.7 JEditorPane类
1、JEditorPane类:Swing中一个能自动加载显示普通文本、HTML文本、RTF文件的类
2、缺陷:含有Script代码的页面容易显示错乱 ,只能用于静态页面的读取
3、模型 
 <span style="color:#000000;">void main(){
       try{
           if(urlStr.startsWith("http://"));  //当URL地址以 http://开头时不做处理                             
             //当URL以www.开头时,添加“http://”前缀
           else if(urlStr.startsWith("www.")){
                urlStr = "http://" + urlStr;
           }
             //当URL为本地文件时,将其包装为一个File类,再通过他获取绝对地址;
           else{
                 File file = new File(urlStr);
                 urlStr = "file:" + file.getAbsolutePath();
            }
           URL url = new URL(urlString);
                 JEditorPane jep = new JEditorPane(url);
                 jep.setContentType("text/html;charset=utf-8");  //解决中文字符乱码的问题
                 jep.setPage(url);    //在窗体上显示url定位的文件的文本内容
       }catch(IOException ex){
       } 
  }</span>


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值