在我们日常开发中,尤其是从事web开发的童鞋们,一些基础网络知识是必备的。平时大家获取都是碎片化的知识,为此我进行了系统性的总结。
本文对网络应用层通信进行了总结,看完后大家会对应用间的通信有进一步的认识,实乃居家旅行必备好文,希望可以帮助到大家。
一切都要从万维网的诞生讲起:
万维网WWW 也称为Web、3W等。
是一个分布式的超媒体(图形,声音,动画等)系统,是超文本(文本信息)系统的扩充。
WWW是基于客户机/服务器方式的 。客户程序向服务器程序发送请求,服务器程序向客户程序送回客户要的万维网文档。
若想标志定位分布在整个互联网的万维网文档,就需要使用URL(统一资源定位符)
URL表示从互联网上得到的资源位置和访问这些资源的方法。
URL格式(想必大家都很熟)
<协议>://<域名>:<端口>/<路径>
协议就是用来实现万维网上的链接,最常用的就是HTTP协议了,还有少数网站使用加密的HTTPs协议。
终于到了重头戏,应用层协议HTTP。
它存在的意义就是解决浏览器怎样向万维网服务器请求万维网文档。
http协议特点:
图示HTTP/1.0 工作:
请求一个万维网文档所需时间(T)= 2 * RTT + 文档传输时间 ;
特点:
HTTP/1.1 则很好的解决了问题。
其特点:
HTTP请求报文和响应报文都是由三部分构成:
序号 | 方法 | 描述 |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | DELETE | 请求服务器删除指定的页面。 |
6 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
9 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 |
最常用的就是 GET 和 POST 方法
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用;
下面是常见的HTTP状态码:
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
万维网用户可以根据Cookie来追踪用户,客户端和服务端通过cookie来传递状态信息。
其在实际网络是怎样工作的呢?
Set-cookin:31d4dk4535ff567
Cookie:31d4dk4535ff567
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。
session与Cookie的区别:
1. session存储数据在服务器端,Cookie在客户端
2. session没有数据大小限制,Cookie有
3. session数据安全,Cookie相对于不安全
日常网络使用中,我们经常使用应用来与服务器通信,那么具体过程是怎样的呢?
大多数操作系统使用系统调用的机制在应用程序和操作系统之间传递控制权。
当某个应用进程启动系统调用是时,控制权就从应用进程传递给了系统调用接口。此接口再把控制权传递给操作系统。操作系统把这个调用转给某个内部过程,并执行请求的操作。
目前使用最广泛的可供应用程序使用的TCP/IP的应用编程接口API就是套接字接口(socket interface)(或插口接口)。
在讨论网络编程时,常常把套接字(socket)作为应用进程和运输层之间的接口。
UDP情况也是类似的,只是UDP是无连接的,通信两端也可以用套接字表示。
套接字(Socket)是应用进程为了获取网络的通信服务而与操作系统进行交互使用的一种机制。
有了背景知识,我们看看在java中网络编程中是怎样操作的吧!
TCP协议是面向连接的,是可靠的运输层协议。
操作步骤:
socket
实例。在网络编程中,一定是Client端 和Server端 同时编写,两者需要实时通信;close()
方法。代码永远最直观,最有效,接下来我们一起欣赏helloworld():
/* 范例名称:简单的client/server程序
* 源文件名称:TestClient.java/TestServer.java
* 要 点:
* 1. Java Socket编程步骤
* 2. Socket/ServerSocket类用法
* 3. 通过Socket对象可以获取通信对方Socket的信息
*/
import java.net.*;
import java.io.*;
public class TestServer {
public static void main(String args[]) {
try {
//创建ServerSocket实例对象,指定TCP监听端口
ServerSocket s = new ServerSocket(8888);
//Server 端对服务进行了分离,主服务器进程负责监听,接受 连接请求,一旦接受请求,就创建从属服务器进程负责处理连接
while (true) {
//接受Client的连接请求,返回Server端socket对象,建立连接(s1负责)
Socket s1 = s.accept();
//获取Server端socket对象的IO流,进行数据传输
OutputStream os = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("Hello," + s1.getInetAddress() +
"port#" +s1.getPort() + " bye-bye!");
//关闭流
dos.close();
//释放连接
s1.close();
}
}catch (IOException e) {
e.printStackTrace();
System.out.println("程序运行出错:" + e);
}
}
}
/* 范例名称:简单的client/server程序
* 源文件名称:TestClient.java/TestServer.java
* 要 点:
* 1. Java Socket编程步骤
* 2. Socket/ServerSocket类用法
* 3. 通过Socket对象可以获取通信对方Socket的信息
*/
import java.net.*;
import java.io.*;
public class TestClient {
public static void main(String args[]) {
try {
//建立连接,创建Socket实例,指定server IP,和TCP端口
Socket s1 = new Socket("127.0.0.1", 8888);
//获取Socket实例的流
InputStream is = s1.getInputStream();
DataInputStream dis = new DataInputStream(is);
System.out.println(dis.readUTF());
//关闭流
dis.close();
//释放TCP连接
s1.close();
} catch (ConnectException connExc) {
connExc.printStackTrace();
System.err.println("服务器连接失败!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP是无连接的,所以将数据打包传输;
在UDP传输中,并没有明确的客户端服务端概念,两者的地位是相同的,所做的动作也是相同的。
操作步骤:
import java.net.*;
import java.io.*;
public class TestUDPClient
{
public static void main(String args[]) throws Exception
{
long n = 10000L;
//long类型数据 利用流转换成字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(n);
byte[] buf = baos.toByteArray();
//打包 字节数组数据,指定目的主机端口
DatagramPacket dp = new DatagramPacket(buf, buf.length,new InetSocketAddress("127.0.0.1", 5678));
//创建套接字,指定UDP端口(本机)
DatagramSocket ds = new DatagramSocket(9999);
//发送数据包
ds.send(dp);
//释放套接字(DatagramSocket)
ds.close();
}
}
import java.net.*;
import java.io.*;
public class TestUDPServer
{
public static void main(String args[]) throws Exception
{
byte buf[] = new byte[1024];
//创建数据包,用来接收数据
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//创建套接字,指定监听端口
DatagramSocket ds = new DatagramSocket(5678);
while(true)
{
//接收数据,并放入buf[]中
ds.receive(dp);
//利用流转换,读取
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readLong());
}
}
}