Socket
socket提供了与外部网络通信的网络接口
InetAddress
InetAddress 提供了一些获取ip地址信息的方法
1 2 3 4 5 6
| static InetAddress getByName(String host) static InetAddress[] getAllByName(String host) static InetAddress getLocalHost() byte[] getAddress() String getHostAddress() String getHostName()
|
创建一个Socket Server
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
| import java.io.* ; import java.net.*; import java.nio.charset.StandardCharsets; import java.util.*;
class Echoserver{ public static void main(String[] args) throws Exception{ try(var s = new ServerSocket(8189)){ try(Socket incoming = s.accept()){ InputStream inStream = incoming.getInputStream(); OutputStream outStream = incoming.getOutputStream(); try(var in = new Scanner(inStream, StandardCharsets.UTF_8)){ var out = new PrintWriter(new OutputStreamWriter(outStream,StandardCharsets.UTF_8),true); out.println("Hello! Enter BYE to exit."); var done = false; while(!done&&in.hasNextLine()){ String line = in.nextLine(); out.println("Echo:"+line); if(line.trim().equals("BYE")) done = true; } } } }; }
}
|
当前的服务器 只能接受一个用户请求,使用 多线程将它改造为接受多个用户请求
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
| import java.io.* ; import java.net.*; import java.nio.charset.StandardCharsets; import java.util.*;
class Echoserver{ public static void main(String[] args) throws Exception{ try(var s = new ServerSocket(8189)){ int i = 0; while(true){ Socket incoming = s.accept(); Runnable thread_mission = new ThreadedHandler(incoming); Thread t = new Thread(thread_mission); t.start(); } } }
}
class ThreadedHandler implements Runnable { private Socket incoming; ThreadedHandler(Socket incoming){ this.incoming = incoming; } @Override public void run(){ try { InputStream inStream = incoming.getInputStream(); OutputStream outStream = incoming.getOutputStream(); try(var in = new Scanner(inStream, StandardCharsets.UTF_8)){ var out = new PrintWriter(new OutputStreamWriter(outStream,StandardCharsets.UTF_8),true); out.println("Hello! Enter BYE to exit."); var done = false; while(!done&&in.hasNextLine()){ String line = in.nextLine(); out.println("Echo:"+line); if(line.trim().equals("BYE")) done = true; } }catch(Exception e){ e.printStackTrace(); } } catch (Exception e) { } } }
|
从这里可以看出TCP端口虽然是固定的,但操作系统通过为每个连接分配唯一的 socket(基于四元组标识)来实现多个连接共用一个监听端口。应用程序通常为每个 socket 启动一个线程或事件循环进行数据处理,从而实现高并发连接的处理。
半关闭
1 2 3 4 5 6 7 8 9 10 11 12
| tar (var socket = new Socket(host,port)){ var in = new Scanner(socket.getInputStream(),StandardCharsets.UTF_8); var writer = new PrintWriter(socket.getOutputStream()); writer.print(...); writer.flush(); socket.shutdownOutput(); while(in.hasNextLine() !=null ) { String line = in.next.line; ... } }
|
URL
java提供了url 对象来对web 数据的访问地址进行封装
1 2
| InputStream inStream = url.OpenStream(); var in = new Scanner(inStream,StandardCharsets.UTF-8);
|
urlconnection
从url中获取更多的内容
1
| URLConnection connection = url.openConnecton();
|
URL
1 2
| InputStream openStream() URLConnection openConnection()
|
URLConnection
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
| void setDoInput()
boolean getDoInput()
void setDoOutput()
boolean getDoOutput()
void setIfModifiedSince(long time)
long getIfModifiedSince()
void setConnectTimeout() int getConnectTimeout()
int getReadTimeout() void setReadTimeout()
void setRequestProperty(String key ,String value) Map<String,List<String>> getRequestProperties()
void connect()
Map<String, List<String>> getHeaderFields()
String getHeaderFileKey(int n) String getHeaderField(int n)
int getContentLength()
String getConnentType()
String getContentEncoding()
long getDate() long getExpiration() long getLastModifed()
InputStream getInputStream()
OutputStream getOutputStream()
Object getContent()
|
HTTP 客户端
1 2 3 4 5 6
| HttpClient client = HttpClient.newHttpClient() HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build() HttpClient client = HttpClient.newBuilder().uri(new URI("<http://horstmann.com>")).GET().build()
HttpClient client = HttpClient.newBuilder().uri(new URL(url)).POST(HttpRequest.BodyPublishers.ofString(jsonString)).build())
|
通过 HttpResponse 接收客户端响应
HttpResponse<T>
类 接收一个 经过响应处理器(HttpResponse.BodyHandlers.ofString())处理的响应对象
1
| HttpResponse<String> response = client.send(request,HttpResponse.BodyHandlers.ofString());
|
通过HttpResponses 还可以获取头信息和状态码
1 2 3 4 5 6 7 8 9 10 11 12
| int status = response.statusCode(); HttpHeaders responseHeaders = response.headers(); Map<String,List<String>> headerMap = responseHeaders.map(); Optional<String> lastModified = responseHeaders.firstValue("Last-Modified");
ExecutorSevice executor = Executor.newCachedThreadPool(); HttpClient client = HttpClient.newBuilder().executor(executor).build();
HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build(); client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenAccept(response->);
|
方法签名
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
| HttpClient static HttpClient newHttpClient()
static HttpClient.Builder newBuilder()
<T> HttpResponse<T> send(HttpRequest request , HttpResponse.BodyHandler<T> responseBodyHandler)
<T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request, HttpResponse.BodyHandler // 使用sendAsync 发送一个异步请求, 后续使用thenAccept接收异步响应的处理 <T> responseBodyHandler )
HttpClient.Builder HttpClient build()
HttpClient.Builder followRedirects(HttpClient.Redirect policy(ALWAYS, NEVR,NORMAL))
HttpClient.Builder executor(Executor executor)
HttpRequest HttpRequest.Builder newBuilder()
HttpRequest.Builder HttpRequest build()
HttpRequest.Builder uri(URI uri)
HttpRequest.Builder GET()
HttpRequest.Builder DELETE()
HttpRequest.Builder POST(HttpRequest.BodyPublisher bodyPublisher)
HttpRequest.Builder PUT(HttpRequest.BodyPublisher bodyPublisher)
HttpResponse T body()
int statusCode()
HttpHeaders headers()
HttpHeaders Map<String , List<String>> map()
Optional<String> firstValue(String name)
|