網絡基礎知識
- 端口號1024以下的儘量不要使用(大多已被互聯網廠商使用)
- 資源定位:
URL(Uniform Resource Locator) 統一資源定位器,他是一種具體的URI
URI(Uniform Resource Identifier) 統一資源標識符,用來唯一的標識一個資源
InetAddress類和InetSocketAddress類
/**
* InetAddress類的使用
* 沒有封裝端口
* @author L J
*/
public class InetDemo {
public static void main(String[] args) throws UnknownHostException {
//通過getLocalHost()方法創建InetAddress對象
InetAddress addr = InetAddress.getLocalHost();
System.out.println(addr.getHostAddress()); //本機IPv4地址:10.56.0.107
System.out.println(addr.getHostName()); //輸出本機計算機名
//根據域名得到InetAddress對象
addr = InetAddress.getByName("www.baidu.com");
System.out.println(addr.getHostAddress()); //返回百度服務器的IP地址:180.97.33.107
System.out.println(addr.getHostName()); //www.baidu.com
//根據IP地址得到InetAddress對象
addr = InetAddress.getByName("180.97.33.107");
System.out.println(addr.getHostAddress()); //返回百度服務器的IP地址:180.97.33.107
System.out.println(addr.getHostName()); //180.97.33.107
}
}
/**
* InetSocketAddress類的使用
* 在InetAddress的基礎上+端口
* @author L J
*/
public class InetDemo2 {
public static void main(String[] args) {
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9999);
System.out.println(address.getHostName()); //127.0.0.1
System.out.println(address.getPort()); //9999
InetAddress addr = address.getAddress();
System.out.println(addr.getHostAddress()); //127.0.0.1
System.out.println(addr.getHostName()); //127.0.0.1
}
}
URL
組成:協議+資源所在的主機域名+端口號+資源文件
public class URLDemo {
public static void main(String[] args) throws MalformedURLException {
//絕對路徑構建
URL url = new URL("http://www.baidu.com:80/index.html#a?username = root");
System.out.println("協議:" + url.getProtocol()); //http
System.out.println("域名:" + url.getHost()); //www.baidu.com
System.out.println("端口:" + url.getPort()); //80
System.out.println("資源:" + url.getFile()); // /index.html
System.out.println("相對路徑:" + url.getPath()); // /index.html
System.out.println("錨點:" + url.getRef()); //a?username = root
//getQuery方法,如果存在錨點,返回null;不存在就返回參數
System.out.println("參數:" + url.getQuery()); //null,如果去掉#a,返回username = root
//相對路徑構建
url = new URL("http://www.baidu.com:80/a/");
url = new URL(url, "b");
System.out.println(url.toString()); // http://www.baidu.com:80/a/b
}
}
/**
* 獲取資源
* 爬蟲第一步
* @author L J
*/
public class URLDemo2 {
public static void main(String[] args) throws IOException {
URL url = new URL("http://www.baidu.com");
/*獲取資源網絡流
InputStream is = url.openStream();
byte[] buf = new byte[1024];
int len = 0;
while(-1 != (len = is.read(buf))) {
System.out.println(new String(buf, 0 ,len));
}
is.close();
*/
BufferedReader br =
new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("F:/DB/baidu.html"), "UTF-8"));
String msg = null;
while((msg = br.readLine()) != null) {
bw.append(msg);
bw.newLine();
}
bw.flush();
bw.close();
br.close();
}
}
聊天室+私聊
發送數據線程:
/**
* 發送數據線程
* @author L J
*/
public class Send implements Runnable{
private BufferedReader console; //控制檯輸入流
private DataOutputStream dos; //輸出流
private boolean isRunning = true; //線程是否存活
private String name; //暱稱
public Send() {
console = new BufferedReader(new InputStreamReader(System.in));
}
public Send(Socket client, String name) {
this();
try {
dos = new DataOutputStream(client.getOutputStream());
this.name = name;
send(this.name);
} catch (IOException e) {
isRunning = false;
//關閉輸出流和控制檯輸入流
CloseUtil.close(dos, console);
}
}
//從控制檯讀取數據
private String getMsgFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
//發送數據
public void send(String msg) {
try {
if(msg != null && !msg.equals("")) {
dos.writeUTF(msg);
dos.flush();
}
} catch (IOException e) {
isRunning = false;
//關閉輸出流和控制檯輸入流
CloseUtil.close(dos, console);
}
}
/**
* 1、從控制檯讀取數據
* 2、發送數據
*/
@Override
public void run() {
while(isRunning) {
send(getMsgFromConsole());
}
}
}
接收數據線程:
/**
* 接收數據線程
* @author L J
*/
public class Receive implements Runnable{
private DataInputStream dis; //輸入流
private boolean isRunning = true; //線程是否存活
public Receive() {
}
public Receive(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dis);
}
}
/**
* 接收數據
* @return 接收到的數據
*/
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dis);
}
return msg;
}
@Override
public void run() {
while(isRunning) {
System.out.println(receive());
}
}
}
關閉流工具:
/**
* 關閉流工具類
* @author L J
*/
public class CloseUtil {
//關閉流
public static void close(Closeable ... io) {
for(Closeable temp : io) {
if(temp != null) {
try {
temp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
客戶端:
/**
* 聊天客戶端
* 1、寫出數據:輸出流
* 2、讀取數據:輸入流
*
* 輸入與輸出在同一個線程內,應該獨立處理
*
* @author L J
*/
public class ChatClient {
public static void main(String[] args) throws IOException, IOException {
Socket client = new Socket("localhost", 9999);
System.out.println("請輸入暱稱:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
if(name.equals("")) {
return;
}
//發送數據,一條獨立的路徑
new Thread(new Send(client, name)).start();
//接收數據,一條獨立的路徑
new Thread(new Receive(client)).start();
}
}
服務器端:
/**
* 聊天服務器
*
* @author L J
*/
public class ChatServer {
//管理道路
private List<MyChannel> all = new ArrayList<MyChannel>();
public static void main(String[] args) throws IOException {
new ChatServer().start();
}
public void start() throws IOException {
ServerSocket server = new ServerSocket(9999);
while(true) {
Socket client = server.accept();
MyChannel channel = new MyChannel(client);
all.add(channel); //統一管理所有的道路
new Thread(channel).start(); //一條道路
}
}
/**
* 一個客戶端一條道路
* @author L J
*/
private class MyChannel implements Runnable {
// 輸入流
private DataInputStream dis;
// 輸出流
private DataOutputStream dos;
//暱稱
private String name;
// 線程是否存活
private boolean isRunning = true;
// 一個客戶端一條道路
public MyChannel(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
this.name = dis.readUTF();
this.send("歡迎進入聊天室!");
sendToOthers(this.name + "加入了聊天室!", true);
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dos, dis);
}
}
/**
* 接收數據
* @return 接收到的數據
*/
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.close(dis);
all.remove(this); //將出錯的道路移除
}
return msg;
}
/**
* 發送數據
*
* @param msg
*/
public void send(String msg) {
if (msg == null && msg.equals("")) {
return;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
isRunning = false;
// 關閉輸入輸出流
CloseUtil.close(dos);
all.remove(this); //將出錯的道路移除
}
}
/**
* 發送數據給其他客戶端
*/
private void sendToOthers(String msg, boolean sys) {
//是否爲私聊
if(msg.startsWith("@") && msg.indexOf(":") > -1) {//私聊
//獲取暱稱
String name = msg.substring(1, msg.indexOf(":"));
String content = msg.substring(msg.indexOf(":") + 1);
for(MyChannel theOne : all) {
if(theOne.name.equals(name)) {
theOne.send(this.name + ":" + content);
}
}
}else{//羣聊
//遍歷容器
for(MyChannel other : all) {
//不發送給自己
if(other == this) {
continue;
}else{
if(sys) {//系統信息
other.send("系統信息:" + msg);
}else{
//發送給其它客戶端
other.send(this.name + ":" + msg);
}
}
}
}
}
/**
* 接收數據,併發送給其他客戶端
*/
@Override
public void run() {
while(isRunning) {
sendToOthers(receive(), false);
}
}
}
}