您的位置:首页 > 理论基础 > 计算机网络

java笔记30 网络编程2 服务器

2015-06-21 10:36 676 查看
1.       客户端与服务器

    最常见的客户端:浏览器,IE/chrome。

最常见的服务端:服务器,Tomcat。

2.       服务器原理

看一下向服务器发送了什么请求。

import java.io.IOException;

import java.io.*;

import java.net.*;

public class H_04ServerDemo

{

public static void main(String[] args) throws Exception

{

ServerSocket ss=new ServerSocket(11000);

Socket s=ss.accept();

System.out.println(InetAddress.getLocalHost().getHostAddress());

InputStream in=s.getInputStream();

byte [] buf=new byte[1024];

int len=in.read(buf);

System.out.println(new String(buf,0,len));

PrintWriter out=new PrintWriter(s.getOutputStream(),true);

out.println("<font color='red' size='7'> 大家好</font>");

s.close();

ss.close();

}

}

运行后打开浏览器 http://192.168.0.100:11000/

                    显示红色7号字体的“大家好”

控制台打印以下信息:

192.168.0.100
GET / HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-mfe-ipt, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.6,en;q=0.4,ja;q=0.2
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; McAfee; InfoPath.2)
Host: 192.168.0.100:11000
Connection: Keep-Alive
 
 
 

这个是请求消息头。

        

    协议 +  地址  + 端口 +路径+ 文件    请求头 GET / HTTP/1.1     发送get请求//Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-mfe-ipt, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */    //支持的内容/**Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.6,en;q=0.4,ja;q=0.2    //支持的语言Accept-Encoding: gzipdeflate    //压缩方式User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; WOW64;Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; McAfee; InfoPath.2)Host: 192.168.0.100:11000    主机名 和端口Connection: Keep-Alive //此处有空行   

如果模拟将以上信息发送给服务器,就可以达到自定义浏览器的效果。

3.       自定义浏览器

import  java.io.*;
import java.net.*;//我的ie客户端,需要tomcat支持
public class H_06MyIE {
    public static void main(String[] args) throws Exception, IOException {
            Socket s=new Socket("192.168.0.100",8080);
            PrintWriter out=new PrintWriter(s.getOutputStream(),true);
            out.println("GET /myweb/demo.html  HTTP/1.1" );//需要一个tomcat服务器 通过服务器访问 /myweb/demo.html
            out.println("Accept: */*");
            out.println("Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.6,en;q=0.4,ja;q=0.2");
            out.println("Host: 192.168.0.100:11000");
            out.println("Connection: Keep-Alive");
            out.println();
            out.println();
           
            BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
            String line=null;
            while((line=bufr.readLine())!=null)
            {
                System.out.println(line);
            }          
            s.close();         
    }
}

此处可以结合GUI,做一个建议IE程序,一个小文本框输入地址,一个文本区域显示得到的信息。

4.       URL&URLConnection

URI:Uniform Resource Identifier统一资源标示符。

URL:Uniform Resoure Locator统一资源定位器,也就是说根据URL能够定位到网络上的某个资源,它是指向互联网“资源”的指针。

    每个URL都是URI,但不一定每个URI都是URL。这是因为URI还包括一个子类,即统一资源名称(URN),它命名资源但不指定如何定位资源。

import  java.net.*;
import java.io.*;
public class H_08URLConnection
{
    public static void main(String[] args) throws Exception
    {
        URL url=new URL("http://www.sina.com");
        sop(url.getProtocol());
        sop(url.getHost());
        sop(url.getPort());//不指定返回-1,此时要设定默认值80
        sop(url.getPath());
        sop(url.getFile());
        sop(url.getQuery());
 
        URLConnection urlc=url.openConnection();//返回内容不带应答信息,被解析了
        //sop(urlc);
        InputStream in=urlc.getInputStream();
        byte[] buf=new byte[1024];
        int len=in.read(buf);
        sop(new String(buf,0,len));
    }
    public static void sop(Object obj)
    {
        System.out.println(obj);
    }
}

返回结果

httpwww.sina.com-1  null<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><style>@charset "utf-8";<style>body,div,span,p,iframe,a{margin:0;padding:0;outline:0}.ad-dialog{position:absolute;z-index:998;padding:0;font-size:12px;overflow:hidden;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;box-shadow:1px 2px 2px #999;-webkit-box-shadow:1px 2px 2px #999;-moz-box-shadow:1px 2px 2px #999}.ad-dialog .title{width:100%;height:25px;line-height:25px;text-align:left;text-indent:8px;font-size:12px;font-weight:bold;color:#FFF;background:#CCC;-webkit-border-top-left-radius:4px;-moz-border-top-left-radius:4px;border-top-left-radius:4px;-webkit-border-top-right-radius:4px;-moz-border-top-right-radius:4px;border-top-right-radius:4px}.ad-dialog .icon{position:absolute;top:0;right:0;margin-right:4px}.ad-dialog .icon a{width:20px;height:20px; 

 

5.       常见网络结构

1、C/S client/server

特点:  该结构的软件,客户端和服务端都需要编写。

            开发成本较高,维护较为麻烦。

好处:  客户端在本地可以分担一部分任务。例如,杀毒软件直接对本机文件进行杀毒。

2、B/S browser/server   

特点: 该结构的软件,只开发服务器端,不开发客户端,因为客户端直接由浏览器取代。

            开发成本相对低,维护更为简单。

 缺点:所有运算都要在服务端完成。

 

6.       练习

传输图片,服务端结合多线程

/*
        客户端
        1、创建服务端点
        2、读取客户端已有的图片数据
        3、通过socket输出流将数据发给服务端
        4、读取服务端反馈信息
        5、关闭
 */
 
package day24;
import java.io.*;
import java.net.*;
public class H_01TcpJpgClient
{
         public static void main(String[] args) throws Exception, Exception
         {
                    Socket s=new Socket(InetAddress.getLocalHost(),10008);
                    //读取文件
                    BufferedInputStream bis=new BufferedInputStream(new FileInputStream("copy.png"));
                    //输出到网络
                    PrintStream ps=new PrintStream(s.getOutputStream());
                    byte [] buf=new byte[1024];
                    int len=0;
                    while((len=bis.read(buf))!=-1)
                    {
                             ps.write(buf, 0, len);
                    }
                    s.shutdownOutput();//结束标记  否则不会结束
                    
                    BufferedInputStream bisin=new BufferedInputStream(s.getInputStream());
                    byte[] bufin=new byte[1024];
                    int  chs=bisin.read(bufin);
                    System.out.println(new String(bufin,0,chs));                 
                    bis.close();
                    s.close();
         }
}
/*
        服务端
        有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程
         这时B客户端连接,只有等待。
         因为服务端还没有处理完A客户端的请求,还有玄幻回来执行下次accept方法,所以暂时获取不到B客户端请求。
 
        为了可以让多个客户端同时并发访问服务端
        将每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户端请求
       
        如何定义该线程
        把客户端封装进入线程
       
 */
 
package day24;
import java.io.*;
import java.net.*;
public class H_01TcpJpgServer
{
         public static void main(String[] args) throws Exception
         {
                   ServerSocket ss=new  ServerSocket(10008);
                   while(true)//服务端一直开启
                   {                          
                            Socket s=ss.accept();
                            new Thread(new PicThread(s)).start();// 每次有连接都会创建一个线程
                   }
                  
         }
}
//所有的服务器都是这个方法,非常重要
class PicThread implements Runnable
{
         private Socket s;
         PicThread(Socket s)
         {
                   this.s=s;
         }
         public void run()
         {
                   String ip=s.getInetAddress().getHostAddress();//获取ip
                   int count=1;
                   try
                   {                          
                            BufferedInputStream bis=new BufferedInputStream(s.getInputStream());
                            //解决文件覆盖的问题
                            File file=new File(ip+count+".png");
                            while(file.exists())
                                     file=new File(ip+count+++".png");
                            PrintStream ps=new PrintStream(new FileOutputStream(file));
                            byte[] buf=new byte[1024];
                            int len=0;
                            while((len=bis.read(buf))!=-1)
                            {
                                     ps.write(buf, 0, len);
                            }
                           
                            PrintStream psout=new PrintStream(s.getOutputStream());
                            psout.write("上传成功".getBytes());             
                            ps.close();
                            s.close();
                   } catch (FileNotFoundException e)
                   {
                            e.printStackTrace();
                   } catch (IOException e)
                   {
                                     e.printStackTrace();
                   }
         }
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java笔记