UDP
DatagramSocket:通讯的数据管道
-send 和receive方法
-(可选,多网卡)绑定一个IP和Port
DatagramPacket
-集装箱:封装数据
-地址标签:目的地IP+Port
package org.example.net;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;public class UdpRecv {public static void main(String[] args) throws Exception {DatagramSocket ds = new DatagramSocket(3000);byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf, 1024);System.out.println("UdpRecv:我在等待信息");ds.receive(dp);System.out.println("UdpRecv:我接收到信息");String strRecv = new String(dp.getData(), 0, dp.getLength()) + " from " + dp.getAddress().getHostAddress() + ":" + dp.getPort();System.out.println(strRecv);Thread.sleep(1000);System.out.println("UdpRecv:我要发送信息");String str = "hello world 222";DatagramPacket dp2 = new DatagramPacket(str.getBytes(), str.length(), InetAddress.getByName("127.0.0.1"), dp.getPort());ds.send(dp2);System.out.println("UdpRecv:我发送信息结束");ds.close();}
}
package org.example.net;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;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);System.out.println("UdpSend:我要发送信息");ds.send(dp);System.out.println("UdpSend:我发送信息结束");Thread.sleep(1000);byte[] buf = new byte[1024];DatagramPacket dp2 = new DatagramPacket(buf, 1024);System.out.println("UdpSend:我在等待信息");ds.receive(dp2);System.out.println("UdpSend:我接收到信息");String str2 = new String(dp2.getData(), 0, dp2.getLength()) + " from " + dp2.getAddress().getHostAddress() + ":" + dp2.getPort();System.out.println(str2);ds.close();}
}
TCP
TCP协议:有链接、保证可靠的无误差通讯
-1)服务器:创建一个ServerSocket,等待连接
-2)客户机:创建一个Socket,连接到服务器-
3)服务器:ServerSocket接收到连接,创建一个Socket和客户的Socket建立专线连接,后续服务器和客户机的对话(这一对Sock会在一个单独的线程(服务器端)上运行
4)服务器的ServerSocket继续等待连接,返回1
ServerSocket: 服务器码头
需要绑定port
如果有多块网卡,需要绑定一个IP地址
Socket: 运输通道
-客户端需要绑定服务器的地址和Port
-客户端往Socket输入流写入数据,送到服务端-客户端从Socket输出流取服务器端过来的数据
-服务端反之亦然
服务端等待响应时,处于阻塞状态
服务端可以同时响应多个客户端
服务端每接受一个客户端,就启动一个独立的线程与之对应
客户端或者服务端都可以选择关闭这对Socket的通道
实例
-服务端先启动,且一直保留
-客户端后启动,可以先退出
package org.example.net;import java.io.*;
import java.net.InetAddress;
import java.net.Socket;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());}}}catch (IOException e){e.printStackTrace();}}
}
package org.example.net;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class TcpServer {public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(8001);//驻守在8001端口Socket s = ss.accept();//阻寒,等到有客户端连接上来System.out.println("welcome to the java world");InputStream ips = s.getInputStream();//有人连上来,打开输入流OutputStream ops = s.getOutputStream();//打开输出流// 同一个通道,服务端的输出流就是客户端的输入流;服务端的输入流就是客户端的输出流ops.write("Hello,client!".getBytes()); //输出一句话给客户端BufferedReader br = new BufferedReader(new InputStreamReader(ips));//从客户端读取一句话System.out.println("client said:" + br.readLine());ips.close();ops.close();s.close();ss.close();}catch (IOException e){e.printStackTrace();}}
}
server2 处理多客户端
package org.example.net;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class TcpServer2 {public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(8001);//驻守在8001端口while (true){Socket s = ss.accept();//阻寒,等到有客户端连接上来System.out.println("a new client coming");new Thread(new Worker(s)).start();}}catch (IOException e){e.printStackTrace();}}
}
package org.example.net;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class Worker implements Runnable {Socket s;public Worker(Socket s) {this.s = s;}@Overridepublic void run() {try {System.out.println("server has started");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 + " echo";// dos.writeBytes(strWord + System.getProperty("line.separator"));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();}}
}
HTTP
Java HTTP编程(java.net包)
-支持模拟成浏览器的方式去访问网页
-URL,Uniform Resource Locator,代表一个资源http://www.ecnu.edu.cn/index.html?a=1&b=2&c=3
-URLConnection
获取资源的连接器
根据URL的openConnection(方法获得URLConnection
connect方法,建立和资源的联系通道
getInputStream方法,获取资源的内容
package org.example.net;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;public class URLConnectionGetTest {public static void main(String[] args) {try {String urlName = "https://www.baidu.com";URL url = new URL(urlName);URLConnection connection = url.openConnection();connection.connect();//打印http的头部信息Map<String, List<String>> headers = connection.getHeaderFields();for (Map.Entry<String, List<String>> entry : headers.entrySet()) {String key = entry.getKey();for (String value : entry.getValue()) {System.out.println(key + ":" + value);}}//输出将要收到的内容属性信息System.out.println("-----------------------");System.out.println("getcontentType:"+connection.getContentType());System.out.println("getcontentLength:"+ connection.getContentLength());System.out.println("getcontentEncoding:?"+ connection.getContentEncoding());System.out.println("getDate:"+ connection.getDate());System.out.println("getExpiration:"+ connection.getExpiration());System.out.println("getLastModifed:"+ connection.getLastModified());System.out.println("----------");BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));//输出收到的内容String line ="";while ((line= br.readLine())!= null){System.out.println(line);}} catch (Exception e) {e.printStackTrace();}}
}
package org.example.net;import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;public class URLConnectionPostTest {public static void main(String[] args) throws IOException {String urlstring = "https://tools.usps.com/go/zipLookupAction.action";Object userAgent = "HTTPie/0.9.2";Object redirects = "1";CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));Map<String, String> params = new HashMap<String, String>();params.put("tAddress", "1 Market street");params.put("tcity", "San Francisco");params.put("sstate", "CA");String result = doPost(new URL(urlstring), params,userAgent == null ? null : userAgent.toString(),redirects == null ? -1 : Integer.parseInt(redirects.toString()));System.out.println(result);}public static String doPost(URL url, Map<String, String> nameValuePairs, String userAgent, int redirects) throws IOException {HttpURLConnection connection = (HttpURLConnection) url.openConnection();if (userAgent != null)connection.setRequestProperty("User-Agent", userAgent);if (redirects >= 0)connection.setInstanceFollowRedirects(false);connection.setDoOutput(true);//输出请求的参数try (PrintWriter out = new PrintWriter(connection.getOutputStream())) {boolean first = true;for (Map.Entry<String, String> pair : nameValuePairs.entrySet()) {//参数必须这样拼接a = 1 & b = 2 & c = 3if (first) {first = false;} else {out.print('&');}String name = pair.getKey();String value = pair.getValue();out.print(name);out.print('=');out.print(URLEncoder.encode(value, "UTF-8"));}}String encoding = connection.getContentEncoding();if (encoding == null){encoding = "UTF-8";}if (redirects > 0) {int responseCode = connection.getResponseCode();System.out.println("responsecode:" + responseCode);if (responseCode == HttpURLConnection.HTTP_MOVED_PERM|| responseCode == HttpURLConnection.HTTP_MOVED_TEMP|| responseCode == HttpURLConnection.HTTP_SEE_OTHER) {String location = connection.getHeaderField("Location");if (location != null) {URL base = connection.getURL();connection.disconnect();return doPost(new URL(base, location), nameValuePairs, userAgent, redirects - 1);}}} else if (redirects == 0) {throw new IOException("Too many redirects");}StringBuilder response = new StringBuilder();try (Scanner in = new Scanner(connection.getInputStream(),encoding)){while(in.hasNextLine()){response.append(in.nextLine());response.append("\n");}} catch (IOException e) {InputStream err = connection.getErrorStream();if (err == null) throw e;try (Scanner in = new Scanner(err)) {response.append(in.nextLine());response.append("\n");}}return response.toString();}
}
HTTPClient
java.net.http包
取代URLConnection 支持HTTP/1.1和HTTP/2 实现大部分HTTP方法主要类
-HttpClient -HttpRequest- HttpResponse
package org.example.net;import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;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();}}
}
Httpcomponents
hc.apache.org,Apache出品从HttpClient进化而来,是一个集成的Java HTIP工具包
-实现所有HTTP方法:get/post/put/delete
-支持自动转向
-支持https协议
-支持代理服务器等
NIO
·Buffer 缓冲区,一个可以读写的内存区域-ByteBuffer, CharBuffer, DoubleBuffer, IntBuffer, LongBufferShortBuffer (StringBuffer 不是Buffer缓冲区)
四个主要属性
capacity 容量,position 读写位置
limit 界限,mark标记,用于重复一个读/写操作
Channel 通道
全双工的,支持读/写(而Stream流是单向的)
-支持异步读写
-和Buffer配合,提高效率
-ServerSocketChannel 服务器TCP Socket 接入通道,接收客户端-SocketChannel TCP Socket通道,可支持阻寒/非阻塞通讯-DatagramChannel UDp 通道
-FileChannel 文件通道
elector多路选择器
-每隔一段时间,不断轮询注册在其上的Channel-如果有一个Channel有接入、读、写操作,就会被轮询出来进行后续IO操作
-根据SelectionKey可以获取相应的Channel,
-避免过多的线程
-SelectionKey四种类型
·OP_CONNECT
·OP_ACCEPT
·OP READ
·OP WRITE
package org.example.NIO;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;public class NioClient {public static void main(String[] args) {String host = "127.0.0.1";int port = 8001;Selector selector = null;SocketChannel socketchannel = null;try {selector = Selector.open();socketchannel = SocketChannel.open();socketchannel.configureBlocking(false);//非阻塞//如果直接连接成功,则注册到多路复用器上,发送请求消息,读应答if (socketchannel.connect(new InetSocketAddress(host, port))) {socketchannel.register(selector, SelectionKey.OP_READ);doWrite(socketchannel);} else {socketchannel.register(selector, SelectionKey.OP_CONNECT);}} catch (IOException e) {e.printStackTrace();}while (true) {try {selector.select(1000);Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> it = selectedKeys.iterator();SelectionKey key = null;while (it.hasNext()) {key = it.next();it.remove();try {handleInput(selector, key);} catch (Exception e) {if (key != null) {key.cancel();if (key.channel() != null)key.channel().close();}}}} catch (Exception ex) {ex.printStackTrace();}}}public static void doWrite(SocketChannel sc)throws IOException {byte[] str = UUID.randomUUID().toString().getBytes();ByteBuffer writeBuffer = ByteBuffer.allocate(str.length);writeBuffer.put(str);writeBuffer.flip();sc.write(writeBuffer);}public static void handleInput(Selector selector, SelectionKey key) throws IOException, InterruptedException {if(key.isValid()) {//判断是否连接成功SocketChannel sc = (SocketChannel) key.channel();if (key.isConnectable()) {if (sc.finishConnect()) {sc.register(selector, SelectionKey.OP_READ);}}if (key.isReadable()) {ByteBuffer readBuffer = ByteBuffer.allocate(1024);int readBytes = sc.read(readBuffer);if (readBytes > 0) {readBuffer.flip();byte[] bytes = new byte[readBuffer.remaining()];readBuffer.get(bytes);String body = new String(bytes, "UTF-8");System.out.println("server said :" + body);} else if (readBytes < 0) {//对端链路关闭key.cancel();sc.close();} else; // 读到字节,忽略}Thread.sleep(5000);doWrite(sc);}}
}
package org.example.NIO;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class NioServer {public static void main(String[] args) throws IOException {int port = 8001;Selector selector = null;ServerSocketChannel servChannel = null;try {selector = selector.open();servChannel = ServerSocketChannel.open();servChannel.configureBlocking(false);servChannel.socket().bind(new InetSocketAddress(port), 1024);servChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务器在8001端口守候");} catch (IOException e) {e.printStackTrace();System.exit(1);}while (true) {try {selector.select(1000);Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> it = selectedKeys.iterator();SelectionKey key = null;while (it.hasNext()) {key = it.next();it.remove();try {handleInput(selector, key);} catch (Exception e) {if (key != null) {key.cancel();if (key.channel() != null)key.channel().close();}}}} catch (Exception ex) {ex.printStackTrace();}try {Thread.sleep(500);} catch (Exception ex) {ex.printStackTrace();}}}public static void handleInput(Selector selector, SelectionKey key) throws IOException {if (key.isValid()) {//判断是否连接成功if (key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel sc = ssc.accept();sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);}if (key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();ByteBuffer readBuffer = ByteBuffer.allocate(1024);int readBytes = sc.read(readBuffer);if (readBytes > 0) {readBuffer.flip();byte[] bytes = new byte[readBuffer.remaining()];readBuffer.get(bytes);String request = new String(bytes, "UTF-8");System.out.println("server said :" + request);String response = request + " 666";doWrite(sc,response);} else if (readBytes < 0) {//对端链路关闭key.cancel();sc.close();} else; // 读到字节,忽略}}}public static void doWrite(SocketChannel channel,String response) throws IOException {if (response != null && response.trim().length() > 0) {byte[] bytes = response.getBytes();ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);writeBuffer.put(bytes);writeBuffer.flip();channel.write(writeBuffer);}}
}
AIO
package org.example.Aio;import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.UUID;public class AioClient {public static void main(String[] a){try {AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();channel.connect(new InetSocketAddress("localhost", 8001), null, new CompletionHandler<Void, Void>() {public void completed(Void result, Void attachment){String str = UUID.randomUUID().toString();channel.write(ByteBuffer.wrap(str.getBytes()), null, new CompletionHandler<Integer, Object>() {@Overridepublic void completed(Integer result, Object attachment){try {System.out.println("write " +str + " , and wait response");ByteBuffer buffer = ByteBuffer.allocate(1024);channel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result_num, ByteBuffer attachment) {attachment.flip();CharBuffer charBuffer = CharBuffer.allocate(1024);CharsetDecoder decoder = Charset.defaultCharset().newDecoder();decoder.decode(attachment, charBuffer, false);charBuffer.flip();String data = new String(charBuffer.array(), 0, charBuffer.limit());System.out.println("server said: " + data);try {channel.close();}catch (Exception e){e.printStackTrace();}}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("read error "+ exc.getMessage());}});channel.close();}catch (Exception e){e.printStackTrace();}}public void failed(Throwable exc, Object attachment){System.out.println("write error ");}});}public void failed(Throwable exc, Void attachment){System.out.println("faild ");}});Thread.sleep(10000);}catch (Exception e){e.printStackTrace();}}
}
package org.example.Aio;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousByteChannel;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;public class AioServer {public static void main(String[] args) throws IOException {AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();server.bind(new InetSocketAddress("localhost", 8001));System.out.println(" server is witing at port 8001");server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {@Overridepublic void completed(AsynchronousSocketChannel channel, Object attchment){server.accept(null, this);ByteBuffer buffer = ByteBuffer.allocate(1024);channel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result_num, ByteBuffer attachment) {attachment.flip();CharBuffer charBuffer = CharBuffer.allocate(1024);CharsetDecoder decoder = Charset.defaultCharset().newDecoder();decoder.decode(attachment, charBuffer, false);charBuffer.flip();String data = new String(charBuffer.array(),0,charBuffer.limit());System.out.println("client said: "+data);channel.write(ByteBuffer.wrap((data + " 666").getBytes()));try {channel.close();}catch (Exception e){e.printStackTrace();}};@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("read error "+ exc.getMessage());}});}public void failed(Throwable exc, Object attachment){System.out.println("failed "+ exc.getMessage());}});while (true){try {Thread.sleep(5000);}catch (InterruptedException e){e.printStackTrace();}}}}