使用Java进行网络编程时,由虚拟机实现了底层复杂的网络协议,Java程序只需要调用Java标准库提供的接口,就可以简单高效地编写网络程序。;
网络编程基础:
计算机网络是指两台或更多的计算机组成的网络,在同一个网络中,任意两台计算机都可以直接通信,因为所有计算机都需要遵循同一种网络协议。
互联网是网络的网络(internet),即把很多计算机网络连接起来,形成一个全球统一的互联网。
TCP/IP协议泛指互联网协议,其中最重要的两个协议是TCP协议和IP协议。只有使用TCP/IP协议的计算机才能够联入互联网;
由于计算机网络从底层的传输到高层的软件设计十分复杂,要合理地设计计算机网络模型,必须采用分层模型,每一层负责处理自己的操作。OSI(Open System Interconnect)网络模型是ISO组织定义的一个计算机互联的标准模型,注意它只是一个定义,目的是为了简化网络各层的操作,提供标准接口便于实现和维护。这个模型从上到下依次是:
应用层,提供应用程序之间的通信;
表示层:处理数据格式,加解密等等;
会话层:负责建立和维护会话;
传输层:负责提供端到端的可靠传输;
网络层:负责根据目标地址选择路由来传输数据;
链路层和物理层负责把数据进行分片并且真正通过物理网络传输,例如,无线网、光纤等。
常用协议:
IP协议是一个分组交换,它不保证可靠传输。
而TCP协议是传输控制协议,它是面向连接的协议,支持可靠传输和双向通信。TCP协议是建立在IP协议之上的,简单地说,IP协议只负责发数据包,不保证顺序和正确性,而TCP协议负责控制数据包传输,它在传输数据之前需要先建立连接,建立连接后才能传输数据,传输完后还需要断开连接。TCP协议之所以能保证数据的可靠传输,是通过接收确认、超时重传这些机制实现的。并且,TCP协议允许双向通信,即通信双方可以同时发送和接收数据。TCP协议也是应用最广泛的协议,许多高级协议都是建立在TCP协议之上的,例如HTTP、SMTP等。
UDP协议(User Datagram Protocol)是一种数据报文协议,它是无连接协议,不保证可靠传输。因为UDP协议在通信前不需要建立连接,因此它的传输效率比TCP高,而且UDP协议比TCP协议要简单得
多。选择UDP协议时,传输的数据通常是能容忍丢失的,例如,一些语音视频通信的应用会选择UDP协议。
TCP编程
Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络;
使用Socket进行网络编程时,本质上就是两个进程之间的网络通信。其中一个进程必须充当服务器端,它会主动监听某个指定的端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收数据。
因此,当Socket连接成功地在服务器端和客户端之间建立后:
- 对服务器端来说,它的Socket是指定的IP地址和指定的端口号;
- 对客户端来说,它的Socket是它所在计算机的IP地址和一个由操作系统分配的随机端口号。
编写服务器端程序监听客户端消息。
Java标准库提供了 ServerSocket 来实现对指定IP和指定端口的监听
package com.demo;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServerDemo {
public static void main(String[] args) throws IOException {
//监听8888端口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("启动server....");
while (true){
// 获取客户端信息,返回一个socket实例
Socket socket = serverSocket.accept();
//如果没有客户端连接进来, accept() 方法会阻塞并一直等待。
System.out.println("收到客户端连接了");
//socket.getInputStream(); //接收客户端信息
//socket.getOutputStream(); //发送信息给客户端
}
}
}
编写客户端发送消息:
package com.demo;
import java.io.*;
import java.net.Socket;
public class SocketClient {
public static void main(String[] args) throws IOException {
Socket sock = new Socket("localhost", 8888); // 连接指定服务器和端口
try {
InputStream in = sock.getInputStream();
OutputStream outputStream = sock.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
while (true){
System.out.println(reader.readLine());
writer.write("hello");
writer.flush();
}
}finally {
sock.close();
}
}
}
UDP编程
在Java中使用UDP编程,仍然需要使用Socket,因为应用程序在使用UDP时必须指定网络接口(IP)和端口号。注意:UDP端口和TCP端口虽然都使用0~65535,但他们是两套独立的端口,即一个应用程
序用TCP占用了端口1234,不影响另一个应用程序用UDP占用端口1234。
使用UDP协议通信时,服务器和客户端双方无需建立连接:
- 服务器端用 DatagramSocket(port) 监听端口;
- 客户端使用 DatagramSocket.connect() 指定远程地址和端口;
- 双方通过 receive() 和 send() 读写数据;
- DatagramSocket 没有IO流接口,数据被直接写入 byte[] 缓冲区。
HTTP编程
HTTP是HyperText Transfer Protocol的缩写,翻译为超文本传输协议,它是基于TCP协议之上的一种请求-响应协议。
服务器端的HTTP编程本质上就是编写Web服务器;
客户端的HTTP编程是发送一个HTTP请求,接收服务器响应后,获得响应内容;
Java标准库提供了基于HTTP的包,通过 HttpURLConnection 访问
HTTP;
发送一个请求的简单代码:
package com.demo;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpDemo {
public static void main(String[] args) throws Throwable {
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET"); //设置方法
connection.setConnectTimeout(5000);
connection.connect(); //开始请求
InputStream in = connection.getInputStream(); //获取返回
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
reader.lines().forEach(System.out::println);
}
}