1.4因特網地址
是用一串數字表示的主機地址,一個因特網地址是由4個字節組成,如果需要在主機名和因特網地址之間進行轉換,就需要使用InetAddress類
只要主機操作系統支持IPV6格式的因特網地址,java.net包也支持
靜態的getByName方法可以返回代表某個主機的InteAddress地址。
可以通過調用getAllByName方法來獲取所有主機
InetAdddress
package socket;
import java.net.InetAddress;
public class InetAddressTest {
public static void main(String[] args)throws Exception{
if(args.length > 0){
String host = args[0];
InetAddress[] addresses = InetAddress.getAllByName(host);
for(InetAddress a : addresses){
System.out.println(a);
}
}
else{
InetAddress localHostAddress = InetAddress.getLocalHost();
System.out.println(localHostAddress);
}
}
}
2.1服務器套接字
一旦啓動了服務器程序,它便會等待某個客戶端連接它的接口。
每一個服務器程序,比如一個HTTP Web服務器,都會不間斷地執行這個循環
1.通過輸入數據流從客戶端接受一個命令(“get me this information”)
2.解碼這個客戶端命令
3.手機客戶端所請求的命令
4.通過輸出數據流發送信息給客戶端
package socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class EchoServer {
public static void main(String[] args)throws Exception{
//建立套接字
try(ServerSocket s = new ServerSocket(8189)) {
//用於建立一個負責監控端口8189的服務器,等待連接,該方法阻塞知道當前對象建立連接爲止
try(Socket incoming = s.accept()) {
InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream();
try(Scanner in = new Scanner(inStream,"UTF-8")) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(outStream, "UTF-8"),true);
out.println("Hello, Enter BYE to exit");
boolean done = false;
while (!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo"+ line);
if(line.trim().equals("BYE")) done = true;
}
}
}
}
}
}
2.2爲多個客戶端服務
每當建立一個新的套接字連接, 也就是當調用accept(),將會啓動一個新的線程來處理服務器和該客戶端之間的連接,而主程序將立即返回並等待下一個連接,
操作步驟
1.編譯和運行服務器程序
2.打開數個telnet窗口 cmd -> telnet localhost 8189
3.在這些窗口之間切換,並鍵入命令,注意你可以同時通過這些窗口進行通信
4.當完成之後,切換到你啓動服務器程序的窗口,並使用CTRL+C強行關閉
package socket;
import javax.sound.midi.Soundbank;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ThreadedEchoServer {
public static void main(String[] args){
try(ServerSocket s = new ServerSocket(8189)) {
int i=1;
while(true){
Socket incoming = s.accept();
System.out.println("Spawning" + i);
Runnable r = new ThreadedEchoHandler(incoming);
Thread t = new Thread(r);
t.start();
i++;
}
}
catch (IOException e){
e.printStackTrace();
}
}
static class ThreadedEchoHandler implements Runnable{
private Socket incoming;
public ThreadedEchoHandler(Socket incomingSocket){
incoming = incomingSocket;
}
public void run(){
try(InputStream inStream = incoming.getInputStream();
OutputStream outStream = incoming.getOutputStream()) {
Scanner in = new Scanner(inStream,"UTF-8");
PrintWriter out = new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true);
out.println("HELLO! ENTER BYE to exit");
boolean done = false;
while (!done && in.hasNextLine())
{
String line = in.nextLine();
out.println("Echo"+ line);
if(line.trim().equals("BYE")) done = true;
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
}
2.3半關閉
套接字連接的一端可以終止其輸出,同時仍舊可以接收來自另一端的數據
服務器端將讀取輸入信息,直至到達輸入流的結尾,然後在發送響應
該協議只適用於一站式的服務,例如http服務,在這種服務中,客戶端連接服務器,發送一個請求,捕獲響應信息,然後斷開連接。
Void shutdownOutput() 將輸出流設置爲”流結束”
Void shutdownInput() 輸入流
Boolean isOutputShutdown() 如果輸出已被關閉,則返回true
Boolean isInputShutdown() 輸入被關閉,返回true
3.0可中斷套接字
當連接到一個套接字時,當前線程將會被阻塞直到建立連接或者超時爲止,同樣,當通過套接字讀取數據時,當前線程也會被阻塞直到操作成功或產生超時爲止。
爲了中斷套接字操作,可以使用java.nio包提供的socketChannel類。
通道並沒有與之相關聯的流,實際上,所擁有的的read和write方法都是通過Buffer對象實現的。
如果不想處理緩衝區,可以使用Scanner類從SocketChannel中讀取信息,因爲Scanner有一個帶ReadableByteChannel參數的構造器。
4.1URL和URI
URL 和URLConnection類封裝了大量複雜的實現細節,例如,可以自一個字符串構建一個URL對象
URL url = new URL(urlString);
只想獲取該資源的內容,可以使用URL類中的openStream方法。
URI是個純粹的語法結構,包含用來指定web資源的字符串的各種組成部分,URL是URI的一個特例,包含了用於定位WEB 資源的足夠信息。
在java類庫中,URI類並不包括任何用於訪問資源的方法,它的唯一作用是解析。
URI類的另一個作用是處理絕對標誌符和相對標識符。
4.2使用URLConnection獲取信息
當操作URLConnection對象時,應該小心的安排操作步驟
1.調用URL類中的openConnection方法獲得URLConnection對象
URLConnection connection = url.openConnection()
2.使用以下方法設置任意的請求屬性
setDoInput
setDoOutput //想獲得輸出流,需要調用
setIfModifyedSince //用於告訴連接你只對自某個特定時期以來被修改的時間
setUseCaches //用於命令瀏覽器首先檢查它的緩存
setAllowUserInteraction //用於在訪問有密碼保護的資源時彈出對話框
setRequestProperty //設置對特定協議起作用的任何“名-值(name/value)對”
setConnectTimeout
setReadTimeout
3.調用connect方法連接遠程資源
Connection.connect();
4.與服務器建立連接後,可以查詢頭信息
5.訪問資源數據
package socket;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class URLconnectionTest {
public static void main(String[] args){
try {
String urlName;
if(args.length > 0) urlName = args[0];
else urlName = "http://horstmann.com";
URL url = new URL(urlName);
URLConnection connection = url.openConnection();
if(args.length>2){
String username = args[1];
String password = args[2];
String input = username + ":" + password;
Base64.Encoder encoder = Base64.getEncoder();
String encoding = encoder.encodeToString(input.getBytes(StandardCharsets.UTF_8));
connection.setRequestProperty("Authorization","Basic"+encoding);
}
connection.connect();
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("----------");
String encoding = connection.getContentEncoding();
if (encoding == null) encoding = "UTF-8";
try (Scanner in = new Scanner(connection.getInputStream(), encoding))
{
// print first ten lines of contents
for (int n = 1; in.hasNextLine() && n <= 10; n++)
System.out.println(in.nextLine());
if (in.hasNextLine()) System.out.println(". . .");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}