网络编程&&Http协议&Web服务器模拟

74 阅读5分钟

主要目标:找到互联网上其他计算机并进行通信

计算机网络编程

计算机网络

image.png TCP(Transmission Control Protocal):传输控制协议  可靠协议,web 站点(http

UDP(User Datagram Protocol):用户数据协议   不可靠协议

实现通信的条件:

两台主机的IP地址相同
需要相同的语言:协议(TCP/IP)
需要有相同的端口

网络编程相关术语

IP地址

常用方法名描述
static InetAddress getLocalHost()返回本地主机IP 
static InetAddress getByName(String host)根据主机名或域名获取IP
static InetAddress getByAddress(byte[] addr)根据一个ip地址获得一个IP地址对象
boolean isReachable(int timeout)测试是否能在指定时间内连通该地址 (类似ping)14.215.177.38
查询百度网页连接
InetAddress address = InetAddress.getByAddress(new byte[]{(byte) 14, (byte) 215, (byte) 177, (byte) 38});
System.out.println(address.isReachable(500));

Port端口

查看端口:netstat -an 1.   端口port用来区分不同的应用程序,端口号范围为065535*2(因为TCP协议和UDP协议各有65535个端口),其中01023被系统所保留,如果自定义端口号,建议为1023以后的;

2.   注意:

(1) 同一台机器上不能有两个程序使用同一个端口,会冲突(如果是同一个协议才会冲突,不同协议的端口号可以一致)

(2) 以后开发中最好记住我们用到过的常用软件的端口,避免我们知己设定端口的时候和他们冲突。例如tomcat:8080,80是浏览器默认端口,mysql:3306,oracle:1521,redis:5379等;

URL 统一资源定位符

image.png 通过URL读取网络的文件数据:

练习:将指定URL地址的页面下载下来
//创建输入流
URL url = new URL("https://www.baidu.com/");
InputStream inputStream = url.openStream();
//获取输出流
FileOutputStream fs = new FileOutputStream("C:\Users\19245\Desktop\douban.html");//要让页面打开,一定要加HTML后缀
//导入commons-io的jar包,使用方法
IOUtils.copy(inputStream,fs);
//关流
fs.close();
inputStream.close();

   URLEncoder(编码)与URLDecoder(解码)

String s="affgbsf永恒";
//编码
String encode = URLEncoder.encode(s, "UTF-8");
System.out.println(encode);//affgbsf%E6%B0%B8%E6%81%92
//解码
String decode = URLDecoder.decode(encode, "UTF-8");
System.out.println(decode);//affgbsf永恒

TCP和UDP

TCP(传输控制协议)

基于字节流的传输层,构建一个相对可靠的连接,比如双方需要传输数据之前,就要先构建一个TCP链接,之后才能进行数据传递

UDP

基于数据报,传输数据之前的双方之间不建立连接,直接把数据发送出去,所以效率很高,但不可靠

Socket(套接字)编程

简介

TCP和UDP只是建立了数据传输的协议,然后要用Socket(套接字)来进行实现发生那个信息的功能(QQ之类聊天工具就使用了Socket技术)

TCP编程

步骤:

1.   服务端创建ServerSocket;

2.   通过调用ServerSocket的accept方法监听客户端的连接;

3.   客户端创建Socket并指定服务端的地址以及端口来建立与服务端的连接;

4.   当服务端accept发现客户端连接后,获取对应该客户端的Socket;

5.   双方通过Socket分别获取对应的输入与输出流进行数据通讯;

6.通讯结束后关闭连接

  • 服务器端
//创建服务端
 ServerSocket socket = new ServerSocket(4090);
//监听客户端连接,并返回客户端的Socket
Socket accept = socket.accept();
//从监听到的客户端中获取字节流
InputStream is = accept.getInputStream();
//对于中文不好处理,将字节流转换为字符流
 InputStreamReader reader = new InputStreamReader(is);
 //转换为缓存流,可以一次性读取一行字符串
 BufferedReader reader1 = new BufferedReader(reader);
 //可以一次性读取一行
String readLine = reader1.readLine();
System.out.println(readLine);
is.close();
  • 客户端
//创建客户端并连接IP地址和端口
Socket socket = new Socket("localhost", 4090);
//获取输出流
OutputStream outputStream = socket.getOutputStream();
//转换为字符流
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
//打印字符流
PrintWriter printWriter = new PrintWriter(writer);
printWriter.write("恐龙宝宝");
//手动刷新,类似于提交
writer.flush();
outputStream.close();

编写步骤:

HTTP协议

简介

http协议依赖于TCP协议,需要先建立一个Server的连接,http才能有效的传输数据,是一个短连接,每次获取完就会断掉,请求都是重新连接,http包含一次请求和一次响应(浏览器给服务器发送数据是一次请求(request)。服务器给浏览器反馈数据是一次响应(response))

报文

分为请求报文和响应报文

自定义Web服务器

我们之前学习的 HTML只是通过协议在本地查看,现在可以自定义Web服务器,把HTML页面放入Socket模拟服务器里面,然后浏览器通过http协议来访问,如:http://ip地址:端口号/ *.html

  • 代码实现
        ServerSocket socket = new ServerSocket(9999);
        while (true){
            Socket accept = socket.accept();
            OutputStream os = accept.getOutputStream();
            OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
            PrintWriter pw = new PrintWriter(writer);


            //获取Hello的流
            FileInputStream fis = new FileInputStream("D:\javawork\workspace\javase-8-31Th\web\Hello.html");
            //把字节流转换为字符流
            InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
            BufferedReader br = new BufferedReader(isr);

            pw.println("http1.1 200 OK");//1.设置响应头:协议版本 状态码 状态描述
            pw.println("Content-Type: text/html;charset=UTF-8");//2.设置响应类型和字符编码
//    pw.println("Content-Length: "+file.length());//可以不写
            pw.println();//3.结束头部信息 -- 表示结束头部信息,接下来开始写内容

            String s="";
            while ((s= br.readLine()) !=null){
                pw.write(s);
            }

            pw.close();
            br.close();
        }