第六章. Java网络编程

第六章. Java网络编程

1. Java UDP编程

计算机通讯:数据从一个IP的port出发(发送方),运输到另外一个IP的port(接收方)

  1. 创建Socket
  2. 通过Socket进行操作
  3. 关闭Socket

UDP: User Datagram Protocol
– 用户数据报协议,面向无连接协议
不保证可靠的数据传输
– 发送方也无法得知是否发送成功

  1. 速度快,也可以在较差网络下使用
  2. 简单,节省,经济

1.1UDP主要类

  1. DatagramSocket:通讯的数据管道
    – send 和receive方法
    – (可选,多网卡)绑定一个IP和Port

  2. DatagramPacket
    – 集装箱:封装数据
    – 地址标签:目的地IP+Port

1.2UDP接收,发送流程

  1. 通信双方创建 DatagramSocket,绑定本地主机的IP与port,DatagramSocket ds=new DatagramSocket(3000)
  2. 通信双方定义包
    接收方:定义DatagramPacket dp=new DatagramPacket(buf,1024);//定义接收方每个包的大小
    发送方:定义DatagramPacket dp=new DatagramPacket(str.getBytes(),str.length(), InetAddress.getByName("127.0.0.1"),3000);//定义发送包,发送的str数据,长度与接收方的IP,port
  3. 通过定义的Socket进行操作:
    接收:ds.receive(dp);//ds套接字收到的信息 存储在 dp,消息长于数据包的长度,消息将被截断。
    发送:ds.send(dp);//ds套接字发送 dp
  4. 关闭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响应流程:

  1. 创建Client实例:HttpClient
  2. 创建request请求,设置请求参数:request
  3. 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的响应流程:

  1. 创建Client实例:CloseableHttpClient
  2. 设置request参数:RequestConfig
    创建get请求:HttpGet
    设置get参数:HttpGet
  3. 执行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回归测试
–…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值