一.网络编程的模型
每一个网络应用基本都是由一个服务器进程和一个或多个客户端进程组成.服务器负责管理某种资源,如ftp服务器负责管理一组磁盘文件,web服务器负责管理一些动态或静态资源.网络编程的模型也就是"客户端-服务器端"模型,请注意此处的客户端和服务器均是指的进程,而不是主机,一台主机上可以运行多个服务进程.
二.网络协议
两个不同主机之间需要进行通信,需要利用各种硬件(光纤,路由器,交换机等)实现物理连接组成局域网和广域网.这些网络中的主机如果需要进行通信,就需要遵守相同的约定,即协议.网络中的应用抽象成7层,各层都有对应的协议,这些协议有两种基本的功能即命名方法(确定通信的双方的身份)和传送机制(如何把信息传送过去).
1.网络互联层:IP协议给因特网中的每台主机都分配一个IP地址,实现因特网中的两台主机之间通信;
2.传输层:TCP协议(传输控制协议)提供两个进程间的可靠数据通信,两个进程通信之前需要建立可靠的数据连接;UDP协议,广播式数据传输,传输数据前不需要先建立连接,只是把应用层的数据交给网络层,不保证数据能正确到达目的地
UDP
TCP
通信双方不需要建立连接,占用的系资源少;
通信双方需要建立并维持连接,占用一定的系统资源;
传输数据不可靠,丢包属于正常现象,丢包时会重传;
传输数据可靠,丢包很少发生
与TCP相比,传输效率高,通讯速度快
对传输质量要求不高,要求传输速度更快时使用UDP协议
对传输质量要求较高时使用TCP协议
3.应用层:HTTP协议(超文本转移协议)将应用层的数据进行封装交给传输层,以及将受到的数据包进行解析交给应用程序;
TCP/IP协议主要负责数据的传输,HTTP协议负责数据的封装
三.网络通信的方式
1.socket:
应用程序中如何应用TCP/IP协议将数据包发送给对方呢?此时出现了socket,它不是一种协议,而是对TCP/UDP等协议进行封装以后供程序调用的接口,代码中调用相应的接口,即可将数据发送给对方.这种编程方式叫做socket编程.客户端建立一个socket,服务端建立一个socket,二者建立连接后便可以进行通信,以TCP协议的socket为例,步骤如下:
1)服务端创建一个socket,并且需要指定相应的端口(端口为2字节),此时这个服务进程便于该端口绑定,监听端口的连接请求;
2)客户端创建一个socket,客户端的端口号一般由内核分配,
3)客户端的socket向某IP地址:端口的socket发送连接请求;
4)服务端的socket监听到连接请求后建立连接,此时两个socket便建立了可靠地TCP连接,可以进行通信;
5)通信结束后客户端关闭socket并向服务端发送关闭请求;
6)服务端受到关闭请求后关闭socket
socket是长连接,连接建立后可以多次通信,最后主动关闭连接.实际中可能长时间不通信socket也会断掉,此时需要自己实现心跳机制确保连接不断开;
2.HTTP
HTPP连接其实也是通过socket连接实现的,由浏览器负责建立socket连接,但是HTTP是短连接,每次通信结束后都会断开,下次再重新建立连接.
1)HTTP请求
HTTP请求的报文的结构如下
<Method> <url> <version>
<header name>:<header data>
第一行的内容是必须的:
method:Http请求的Method有 GET,POST,PUT,DELETE,OPTIONS,HEAD,TRACE,最常用的是method
url:HTTP请求的内容的url地址,如果写作"/",表示请求默认页
version:HTTP/1.1
第二行及之后会有零个或多个请求包头,其中最终要的有Host包头,里面包含请求的主机地址和端口
注意:在请求头结束之后都要有一行空行
例:GET http://s1-im-notify.csdn.net/socket.io/1/xhr-polling/L-gy6AKh6VSYTZPeM8Vn?t=1495347224751 HTTP/1.1
Host: s1-im-notify.csdn.net
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36
Origin: http://write.blog.csdn.net
Accept: */*
Referer: http://write.blog.csdn.net/postedit/72570619
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
2)HTTP响应
HTTP相应的结构如下:
<version> <status code> <status message>
<header name>:<header data>
response bod
第一行是必须的:
status code:
1xx:保留值
2xx:服务器已经成功接收了请求,200表示成功;
3xx:重定向;
4XX表示客户端出现了问题,403表示客户端无权访问,404表示未找到请求的资源;
5xx:表示服务端处理请求过程中出了问题;501:服务端未实现请求的方法
status message:结果状态描述
第二行及之后出现0或者多个响应包头,其中重要的有Content-type:响应报文的类型 Content-Length:响应报文体的长度
响应报文头和报文体之间有一个空行,表示报文头终止
最后是相应的报文体
例子:
HTTP/1.1 200 OK
Date: Sun, 21 May 2017 06:27:45 GMT
Content-Type: image/gif
Content-Length: 43
Last-Modified: Wed, 17 Jul 2013 05:44:02 GMT
Connection: keep-alive
ETag: "51e62f22-2b"
Server: Apache
Accept-Ranges: bytes 响应报文头
响应报文头和报文体之间的空行
GIF89a ! , D ; 响应报文体部分
四.Socket编程实践
Java中socket编程涉及到Socket和ServerSocket两个常用类,在java.net包中
1.java.net.InetAddress
InetAddress的实例包含一个ip地址和可能还会包含一个主机名.该类的构造函数私有,需要通过静态方法来获取实例,常用的方法有
1)static InetAddress[] getAllByName(String host):通过主机名获得Inet实例
2)static InetAddress getByAddress(byte[] addr):通过IP地址获得
byte[] ba={(byte)220,(byte)181,(byte)111,(byte)188};
InetAddress ip=InetAddress.getByAddress(ba); 实例:/220.181.111.188
3)static InetAddress getByAddress(String host,byte[] addr):通过主机名和地址获得
4)static InetAddress getByName(String host):通过主机名获得
InetAddress ip2=InetAddress.getByName("www.baidu.com"); 实例:www.baidu.com/220.181.111.188
5)static InetAddress getLocalHost():获得本机的InetAddress实例
2.java.net.Socket
Socket用于创建客户端的socket,
1)构造函数
public Socket():创建一个未连接的socket
public Socket(String host,int port):创建一个socket连接到指定的主机和端口号
public Socket(InetAddress address,int port):创建一个socket连接到指定的主机和端口号
public Socket(String host,int port,InetAddress localAddr,int localPort);创建socket,制定服务端和客户端的主机和端口
public Socket(InetAddress host,int port, InetAddress localAddr,int localPort)创建socket,制定服务端和客户端的主机和端口
2)读取和写入的函数
public InputStream getInputStream():获取一个输入流,将需要发送的数据放入其中
public void shutdowmInput():关闭输入流
public OutputStream get OutputStream ():获取一个输出流,从中获得接收的数据;
public void shutdowmOutput():关闭输出流
以上这些方法都将抛出IOException异常,程序中需要捕获并处理。
3)关闭socket
public void close() throws IOExcepiton
3.java.net.ServerSocket
该类用于创建服务端的socket
1)构造函数
public ServerSocket (int Port):创建socket连接,指定端口号
public ServerSocket (int Port,int backlog):创建socket连接,指定端口号和连接数目
public ServerSocket (int Port,intbacklog,InetAddress bindAddr)创建socket连接,指定端口号,连接数目和服务端地址
2)侦听
public Socket accept():等待客户端的连接,有连接请求时,返回一个socket对象,便可利用socket的读取和写入函数进行通信
3)关闭
public void close():关闭Socket
例1:服务端
package socketserver;
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
ServerSocket ss=new ServerSocket(2020);
while(true){
Socket s1=ss.accept();
DataOutputStream dos=new DataOutputStream(s1.getOutputStream());
dos.writeUTF("This is my first java socket program!");
dos.close();
s1.close();
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
客户端:
package socketprogram;
import java.net.*;
import java.io.*;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
Socket s1=new Socket("127.0.0.1",2020);
DataInputStream dis=new DataInputStream(s1.getInputStream());
String s=new String(dis.readUTF());
System.out.println(s);
s1.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
输出:
This is my first java socket program!
---------------------
作者:乘物游心0823
来源:CSDN
原文:https://blog.csdn.net/lpq374606827/article/details/72570619
版权声明:本文为博主原创文章,转载请附上博文链接!