网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。 java.net 包中的类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。
1. 网络编程常识 1.1 七层网络模型 为了保证数据传输的可靠和安全,ISO(国际标准委员会组织)将数据的传递从逻辑上划分为以下7层: 应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
当发送数据时,需要按照上述七层模型从上到下层层加包再发送出去;
当接收数据时,需要按照上述七层模型从下到上层层拆包再显示出来;
1.2 IP地址
IP地址:是互联网中的唯一地址标识,也就是根据IP地址可以定位到具体某一台设备,IP地址本质上是32位二进制组成的整数叫做IPv4,当然也有128位二进制组成的整数叫做IPv6,目前主流的还是IPv4。
日常生活中采用点分十进制 表示法进行IP地址的描述,也就是将每个字节的二进制转换为一个十进制整数,不同的十进制整数之间采用小数点隔开。如:192.168.1.1
1.3 端口号
根据IP地址可以定位到具体某一台设备,而该设备中启动的进程可能很多,此时可以使用端口号来定位该设备中的具体某一个进程。
网络编程需要提供:IP地址 和 端口号
端口号是16位二进制组成的整数,表示范围是:0 ~ 65535,其中0 ~ 1024之间通常被系统占用,因此网络编程需要从1025开始使用。
1.4 tcp协议与udp协议
TCP(Transmission Control Protocol,传输控制协议) 是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“握手”才能建立起来。
UDP(User Data Protocol,用户数据报协议) 是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
tcp协议与udp协议比较:
tcp协议
udp协议
传输控制协议,面向连接
用户数据报协议,非面向连接
通信过程全程保持连接
通信过程不需要全程连接
保证了数据传输的可靠性和有序性
不保证数据传输的可靠性和有序性
全双工的字节流的通信方式
全双工的数据报的通信方式
服务器的资源消耗多,压力大,效率低
服务器资源消耗少,压力小,效率高
2. 基于tcp协议的编程模型 2.1 编程模型 1 2 3 4 5 6 7 服务器端 客户端 创建监听服务 等待连接 <----建立连接------ 连接服务器 进行通讯 <----进行通讯-----> 进行通讯 关闭连接 关闭连接
服务器:
创建ServerSocket类型的对象并提供端口号;
等待客户端的连接请求,调用accept方法;
使用输入输出流进行通信;
关闭Socket;
客户端:
创建Socket类型的对象并提供服务器的通信地址和端口号;
使用输入输出流进行通信;
关闭Socket;
2.2 ServerSocket类和Socket类
java.net.ServerSocket类主要用于描述服务器套接字信息。
常用方法
ServerSocket(int port)
根据参数指定的端口号来构造对象
Socket accept()
监听并接收到此套接字的连接请求
void close()
用于关闭套接字
java.net.Socket类主要用于描述客户端套接字,是两台机器间通信的端点。
常用方法
Socket(String host, int port)
根据指定主机名和端口号来构造对象
InputStream getInputStream()
用于获取当前套接字的输入流
OutputStream getOutputStream()
用于获取当前套接字的输出流
void close()
用于关闭套接字
3.客户端与服务端通信演示: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 public class ServerThread extends Thread { private Socket s; public ServerThread (Socket s) { this .s = s; } @Override public void run () { try { BufferedReader br = new BufferedReader ( new InputStreamReader (s.getInputStream())); PrintStream ps = new PrintStream (s.getOutputStream()); while (true ) { String str = br.readLine(); if ("bye" .equalsIgnoreCase(str)) { System.out.println("客户端" + s.getInetAddress() + "已下线!" ); break ; } System.out.println("客户端" + s.getInetAddress() + "发来的消息是:" + str); ps.println("I received!" ); } ps.close(); br.close(); s.close(); } catch (Exception e) { e.printStackTrace(); } } } public class ServerStringTest { public static void main (String[] args) { try { ServerSocket ss = new ServerSocket (8888 ); while (true ) { System.out.println("等待客户端的连接请求..." ); Socket s = ss.accept(); System.out.println("客户端" + s.getInetAddress() + "连接成功!" ); new ServerThread (s).start(); } } catch (Exception e) { e.printStackTrace(); } } } public class ClientStringTest { public static void main (String[] args) { try { Socket s = new Socket ("XDL-20170621QCO" , 8888 ); System.out.println("连接服务器成功!" ); Scanner sc = new Scanner (System.in); PrintStream ps = new PrintStream (s.getOutputStream()); BufferedReader br = new BufferedReader ( new InputStreamReader (s.getInputStream())); while (true ) { System.out.println("请输入要发送的内容:" ); String msg = sc.nextLine(); ps.println(msg); System.out.println("客户端发送数据成功!" ); if ("bye" .equalsIgnoreCase(msg)) { System.out.println("聊天结束!" ); break ; } String str = br.readLine(); System.out.println("客户端接收到的数据是:" + str); } br.close(); sc.close(); ps.close(); s.close(); } catch (Exception e) { e.printStackTrace(); } } }
4. 基于udp协议的编程模型 4.1 编程模型
主机A(接收方):
创建DatagramSocket类型的对象,并提供端口号;
创建DatagramPacket类型的对象,用于接收发来的数据;
从Socket中接收数据,调用**receive()**方法;
关闭Socket并释放有关的资源;
主机B(发送方)
创建DatagramSocket类型的对象;
创建DatagramPacket类型的对象,并提供接收方的IP地址和端口号;
通过Socket发送数据,调用**send()**方法;
关闭Socket并释放有关的资源;
4.2 DatagramSocket类
java.net.DatagramSocket类用于描述发送或接受数据报的套接字(邮局点);
常用方法
DatagramSocket()
无参的方式构造对象。
DatagramSocket(int port)
根据参数指定的端口号来构造对象。
void receive(DatagramPacket p)
用于接收数据并存放到参数指定的变量中。
void send(DatagramPacket p)
用于将参数指定的数据发送出去。
void close()
4.3 DatagramPacket类
java.net.DatagramPacket类用于描述数据报信息(信件);
常用方法
DatagramPacket(byte[] buf, int length)
用于接收数据包并记录到参数变量中;
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
用于将参数指定的数据发送到参数指定的位置
InetAddress getAddress()
用于获取发送方或接收方的通信地址信息。
int getPort()
用于获取发送方或接收方的端口信息。
int getLength()
用于获取发送或接收数据的长度。
4.4 InetAddress类
java.net.InetAddress类用于描述互联网协议地址。
常用方法
static InetAddress getLocalHost()
用于获取本地主机的通信地址信息。
static InetAddress getByName(String host)
根据参数指定的主机名来获取通信地址。
String getHostName()
用于获取通信地址中的主机名信息。
String getHostAddress()
用于获取通信地址中的IP地址信息。
原文链接: http://chaooo.github.io/2017/05/22/java-net.html
版权声明: 转载请注明出处.