第六章. Java网络编程
第六章. Java网络编程
1. Java UDP编程
计算机通讯:数据从一个IP的port出发(发送方),运输到另外一个IP的port(接收方)
- 创建Socket
- 通过Socket进行操作
- 关闭Socket
UDP: User Datagram Protocol
– 用户数据报协议,面向无连接协议
– 不保证可靠的数据传输
– 发送方也无法得知是否发送成功
- 速度快,也可以在较差网络下使用
- 简单,节省,经济
1.1UDP主要类
-
DatagramSocket:通讯的数据管道
– send 和receive方法
– (可选,多网卡)绑定一个IP和Port -
DatagramPacket
– 集装箱:封装数据
– 地址标签:目的地IP+Port
1.2UDP接收,发送流程
- 通信双方创建 DatagramSocket,绑定本地主机的IP与port,
DatagramSocket ds=new DatagramSocket(3000)
- 通信双方定义包
接收方:定义DatagramPacket dp=new DatagramPacket(buf,1024);
//定义接收方每个包的大小
发送方:定义DatagramPacket dp=new DatagramPacket(str.getBytes(),str.length(), InetAddress.getByName("127.0.0.1"),3000);
//定义发送包,发送的str数据,长度与接收方的IP,port - 通过定义的Socket进行操作:
接收:ds.receive(dp);
//ds套接字收到的信息 存储在 dp,消息长于数据包的长度,消息将被截断。
发送:ds.send(dp);
//ds套接字发送 dp - 关闭socket:
ds.close()
UdpRecv:
import java.net.*;
public class UdpRecv
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds=new DatagramSocket(3000);//定义Socket套接字
byte [] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,1024);//定义每个包的大小
System.out.println("UdpRecv: 我在等待信息");
ds.receive(dp); //ds套接字收到的信息 存储在 dp,消息长于数据包的长度,消息将被截断。
System.out.println("UdpRecv: 我接收到信息");
String strRecv=new String(dp.getData(),0,dp.getLength()) +
" from " + dp.getAddress().getHostAddress()+":"+dp.getPort();
System.out.println(strRecv);
ds.close();
}
}
UdpSend:
import java.net.*;
public class UdpSend
{
public static void main(String [] args) throws Exception
{
DatagramSocket ds=new DatagramSocket();
String str="hello world";
DatagramPacket dp=new DatagramPacket(str.getBytes(),str.length(),
InetAddress.getByName("127.0.0.1"),3000);//发送的str数据,长度与接收方的IP,port
System.out.println("UdpSend: 我要发送信息");
ds.send(dp);
System.out.println("UdpSend: 我发送信息结束");
ds.close();
}
}
2. Java TCP 编程
TCP:Transmission Control Protocol
– 传输控制协议,面向连接的协议
– 两台机器的可靠无差错的数据传输
– 双向字节流传递
2.1 TCP主要的类
ServerSocket: 服务器码头
– 需要绑定port
– 如果有多块网卡,需要绑定一个IP地址
Socket: 运输通道
– 客户端需要绑定服务器的地址和Port
– 客户端往Socket输入流写入数据,送到服务端
– 客户端从Socket输出流取服务器端过来的数据
– 服务端反之亦然
- 接收,发送是以流的形式,见Java IO包
– getInputStream()获取通道输入流
– getOutputStream()获取通道输出流
– 再对流进行转化,包装
2.2 TCP连接过程:3次握手
– ①服务器:创建一个ServerSocket,等待连接
ServerSocket ss=new ServerSocket(8001);
//绑定本地主机IP,Port
Socket s=ss.accept();
//等待连接,创建专线
– ②客户机:创建一个Socket,连接到服务器
Socket s = new Socket(InetAddress.getByName("127.0.0.1"), 8001);
– ③服务器:ServerSocket接收到连接,创建一个Socket和客户的
Socket建立专线连接,后续服务器和客户机的对话(这一对Socket)
会在一个单独的线程(服务器端)上运行
– ④服务器的ServerSocket继续等待连接,返回①
TcpServer:
import java.net.*;
public class TcpServer2
{
public static void main(String [] args)
{
try
{
ServerSocket ss=new ServerSocket(8001);//绑定本地主机IP,Port
while(true)
{
Socket s=ss.accept();//等待连接,创建专线
System.out.println("来了一个client");
new Thread(new Worker(s)).start();
}
//ss.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
class Worker implements Runnable {
Socket s;
public Worker(Socket s) {
this.s = s;
}
public void run() {
try {
System.out.println("服务人员已经启动");
InputStream ips = s.getInputStream();
OutputStream ops = s.getOutputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(ips));
DataOutputStream dos = new DataOutputStream(ops);
while (true) {
String strWord = br.readLine();//没用输入时阻塞
System.out.println("client said:" + strWord +":" + strWord.length());
if (strWord.equalsIgnoreCase("quit"))
break;
String strEcho = strWord + " 666";
// dos.writeBytes(strWord +"---->"+ strEcho +"\r\n");
System.out.println("server said:" + strWord + "---->" + strEcho);
dos.writeBytes(strWord + "---->" + strEcho + System.getProperty("line.separator"));
}
br.close();
// 关闭包装类,会自动关闭包装类中所包装的底层类。所以不用调用ips.close()
dos.close();
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
TcpClient:
import java.net.*;
import java.io.*;
public class TcpClient {
public static void main(String[] args) {
try {
Socket s = new Socket(InetAddress.getByName("127.0.0.1"), 8001); //需要服务端先开启
//同一个通道,服务端的输出流就是客户端的输入流;服务端的输入流就是客户端的输出流
InputStream ips = s.getInputStream(); //开启通道的输入流
BufferedReader brNet = new BufferedReader(new InputStreamReader(ips));
OutputStream ops = s.getOutputStream(); //开启通道的输出流
DataOutputStream dos = new DataOutputStream(ops);
BufferedReader brKey = new BufferedReader(new InputStreamReader(System.in));
while (true)
{
String strWord = brKey.readLine();
if (strWord.equalsIgnoreCase("quit"))
{
break;
}
else
{
System.out.println("I want to send: " + strWord);
dos.writeBytes(strWord + System.getProperty("line.separator"));
System.out.println("Server said: " + brNet.readLine());
}
}
dos.close();
brNet.close();
brKey.close();
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. Java HTTP 编程
HTTP访问方式
– GET:从服务器获取资源到客户端
– POST:从客户端向服务器发送数据
– PUT:上传文件
– DELETE:删除文件
– HEAD:报文头部
– OPTIONS:询问支持的方法
– TRACE:追踪路径
– CONNECT:用隧道协议连接代理
URL (Uniform Resource Locator):代表一个资源
红色:协议
蓝色:域名,会解析到所在服务器
绿色:资源
黑色:参数,参数不同所获资源不同
3.1 Http第三方库
3.1.1. java.net.http包(JDK自带)
– JDK 9 新增,JDK10更新,JDK11正式发布
– 支持HTTP/1.1和HTTP/2,实现大部分HTTP方法
– 主要类:
HttpClient: 客户实例
HttpRequest : 请求服务器
HttpResponse: 服务器返回数据
java.net.http包的Http响应流程:
- 创建Client实例:
HttpClient
- 创建request请求,设置请求参数:
request
- Client 发出request请求,返回response :
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
JDKHttpClientGetTest:
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.Charset;
public class JDKHttpClientGetTest {
public static void main(String[] args) throws IOException, InterruptedException {
doGet();
}
public static void doGet() {
try{
HttpClient client = HttpClient.newHttpClient();//创建客户实例
HttpRequest request = HttpRequest.newBuilder(URI.create("http://www.baidu.com")).build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body()); //客户发出请求,返回数据
}
catch(Exception e) {
e.printStackTrace();
}
}
}
JDKHttpClientPostTest:
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class JDKHttpClientPostTest {
public static void main(String[] args) throws IOException, InterruptedException {
doPost();
}
public static void doPost() {
try {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://tools.usps.com/go/ZipLookupAction.action"))
//.header("Content-Type","application/x-www-form-urlencoded")
.header("User-Agent", "HTTPie/0.9.2")
.header("Content-Type","application/x-www-form-urlencoded;charset=utf-8")
//.method("POST", HttpRequest.BodyPublishers.ofString("tAddress=1 Market Street&tCity=San Francisco&sState=CA"))
//.version(Version.HTTP_1_1)
.POST(HttpRequest.BodyPublishers.ofString("tAddress="
+ URLEncoder.encode("1 Market Street", "UTF-8")
+ "&tCity=" + URLEncoder.encode("San Francisco", "UTF-8") + "&sState=CA"))
//.POST(HttpRequest.BodyPublishers.ofString("tAddress=" + URLEncoder.encode("1 Market Street", "UTF-8") + "&tCity=" + URLEncoder.encode("San Francisco", "UTF-8") + "&sState=CA"))
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.headers());
System.out.println(response.body().toString());
}
catch(Exception e) {
e.printStackTrace();
}
}
}
3.1.2 HttpComponents(Apache出品)
- 从HttpClient进化而来
- 是一个集成的Java HTTP工具包
– 实现所有HTTP方法:get/post/put/delete
– 支持自动转向
– 支持https协议
– 支持代理服务器等
HttpComponents的Http的响应流程:
- 创建Client实例:
CloseableHttpClient
- 设置request参数:
RequestConfig
创建get请求:HttpGet
设置get参数:HttpGet
- 执行get请求,返回响应request:
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpComponentsGetTest:
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpComponentsGetTest {
public final static void main(String[] args) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000) //设置连接超时时间
.setConnectionRequestTimeout(5000) // 设置请求超时时间
.setSocketTimeout(5000)
.setRedirectsEnabled(true)//默认允许自动重定向
.build();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
httpGet.setConfig(requestConfig);
String srtResult = "";
try {
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
srtResult = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");//获得返回的结果
System.out.println(srtResult);
}else
{
//异常处理
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.1.3…
Http应用:
• 爬虫
• 自动刷票机器人
• 各类Web监控
• Web回归测试
–…