黑马程序员----网络编程二

来源:互联网 发布:剑三军爷捏脸数据 编辑:程序博客网 时间:2024/06/11 10:01

ASP.Net+Android+IO开发S、.Net培训、期待与您交流!

一、实例TCP实现图片上传,对需求的分析
    客户端:1、创建Socket服务
         2、读取客户端已有的图片数据,这里只能用字节流操作数据
   3、通过Socket输出流将图片数据发送到服务器端,并将数据转化为图片信息
   4、读取服务器返馈的信息
   5、关闭
 一下为客户端的代码:
          //1,建立Socket服务
   s = new Socket(InetAddress.getLocalHost(),10006);
   //2、将图片转化为字节流,并写入到Socket的输出流中
   FileInputStream fis = new FileInputStream("aa.jpg");
   OutputStream out = s.getOutputStream();
   byte buf[] = new byte[1024];
   int len = 0;
   while((len = fis.read(buf))>0)
   {
    out.write(buf, 0, len);
   }
   s.shutdownOutput();//3、设置结束标记为-1
   //4、读取服务端的回应信息
   InputStream in = s.getInputStream();
   byte[] bufin = new byte[1024];
   while((len = in.read(bufin))>0)
   {
    System.out.println(new String(bufin,0,len));
   }
 服务器端:1、建立Socket服务,这时使用ServerSocket,并获得客户端的Socket对象
           2、利用客户端Socket对象获得输入流,并将输入流信息,输出到FileOutputStream对象中
     3、给客户端回应相关信息
     4、关闭连接资源
 Server端代码:
         //1、建立Socket服务,这时使用ServerSocket,并获得客户端的Socket对象
         ss = new ServerSocket(10006);
   Socket s = ss.accept();
   //2、利用客户端Socket对象获得输入流,并将输入流信息,输出到FileOutputStream对象中
   FileOutputStream fos = new FileOutputStream("server.jpg");
   InputStream in = s.getInputStream();
   int i = 0;
   byte[] buf = new byte[1024];
   while((i = in.read(buf))>0)
   {
    fos.write(buf, 0, i);
   }
   //3、给客户端回应相关信息
   OutputStream out = s.getOutputStream();
   out.write("上传成功".getBytes());
   // 4、关闭连接资源
   fos.close();
   s.close();
二、如何解决服务端因一个连接而造成的等待现象
    利用多线程实现多个客户端同时上传文件,并将文件按照IP地址分开,如果文件已存在,则将文件名用计数的方式分开,由上面Server端的代码我们知道在每次建立客户端对象后会产生等待问题,所以我们将客户端对象所坐的动作放到线程中去,这样可以实现客户并发的向服务端发送图片
   线程代码
     private Socket s;
  PicThread(Socket s)
  {this.s = s;}
  public void run()
  {
   int count = 1;
   String ip  = s.getInetAddress().getHostAddress();
   .........
    System.out.println(ip+"....connected");
       InputStream in = s.getInputStream();
    File dir =  new File("d:\\pic");
    File file = new File(dir,ip+"("+(count)+")"+".jpg");
    while(file.exists())//避免上传后的图片重名
     file = new File(dir,ip+"("+(count++)+")"+".jpg");
    FileOutputStream fos = new FileOutputStream(file);
    byte[] buf = new byte[1024];
    int len = 0;
    while((len=in.read(buf))!=-1)
     fos.write(buf,0,len);
    OutputStream out = s.getOutputStream();
    out.write("上传成功".getBytes());
    fos.close();
    s.close();
   ......
  }
三、简单的服务器实现
      利用多线程与Socket技术实现简单的服务器,使用多线程技术,可以被多用户访问
   ss = new ServerSocket(10100);
   while(true)
   {Socket s = ss.accept();
   new Thread(new ServerThread(s)).start();}
 多线程部分class ServerThread implements Runnable
   {
    private Socket s ;
    public ServerThread(Socket s )
    {
     this.s = s;
    }
    @Override
    public void run() {
     // TODO Auto-generated method stub
     String ip = s.getInetAddress().getHostAddress();
     System.out.println(ip+"....connected");
     try {
      PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
      pw.print("<h1>欢迎来到快乐家族</h1>");
      pw.println("<a href =\"http://www.baidu.com\">点击,进入百度一下</a>");
      s.close();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   }
四、简单的获得服务器返回的信息
     Socket s = new Socket("127.0.0.1",8080);
     PrintWriter out = new PrintWriter(s.getOutputStream(),true);//用于向服务器传输请求信息
     out.println("GET /myweb/demo.html HTTP/1.1");
     out.println("Accept:*/*");
     out.println("Accpt_Language:zh_cn");
     out.println("Host: 223.78.96.49:11000");
     out.println("Connection: close");
     BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));//获得服务器返回的信息
     String line = null;
     while((line = bufr.readLine())!= null)
     {
      System.out.println(line);
     }
     s.close();
五、URL统一资源定位符和URLConnection对象
     URL对象可以获得我们请求的部分信息,主要通过一下方法来获得String getFile() 获取此 URL 的文件名、 String getHost() 获取此 URL 的主机名(如果适用)、 String getPath() 获取此 URL 的路径部分、 int getPort() 获取此 URL 的端口号、 String getProtocol()、获取此 URL 的协议名称、String getQuery()、 获取此 URL 的查询部分。
  程序代码URL url = new URL("http://www.baidu.com/index.html");
   System.out.println("protocol:"+url.getProtocol());
   System.out.println("host:"+url.getHost());
   System.out.println("file:"+url.getFile());
   System.out.println("path:"+url.getPath());
   System.out.println("port:"+url.getPort());
   System.out.println("query:"+url.getQuery());
    URLConnection对象是基于应用层的URL操作对象,我们可以通过url.openConnection()获得此对象,同时该对象为我们提供了一些操作服务器回应数据的流getInputStream(),这样我们操作对应的流更加方便;下例为获得百度首页信息,并将其保存到文件中的过程
  //1、首先获得对应的URL对象,并通过openConnection获得URLConnection对象,该对象是基于http协议的应用层对象
   URL url = new URL("http://www.baidu.com");
   URLConnection con = url.openConnection();
    //2、通过底层Socket对象的getInputStream方法获得输入流对象
   InputStream in = con.getInputStream();
   byte[] buf = new byte[1024];
   int i = 0;
 //3、定义文件字节流对象,并用于保存获得的网页信息
   FileOutputStream file = new FileOutputStream("baidu.html");
   while((i = in.read(buf))>0){
    file.write(buf, 0, i);
   }
   file.close();//4、关闭流资源

ASP.Net+Android+IOS开发、.Net培训、期待与您交流!