文章目录
1 回顾
- HashMap
- key.hashCode() 得到哈希值,用哈希值来计算下标 i
- 键值对封装成 <mark>Enyry</mark> 实例放入 i 位置
- 空位置,直接放入
- 有数据,<mark>依次用key.equals()方法比较是否相等</mark>
- 找到相等的键,覆盖值
- 没有相等的键,用链表连接在一起
- <mark>负载率,加载因子到0.75 (数据量/容量)</mark>
- 新建翻倍容量的新数组
- 所有数据重新执行哈希运算放入新数组
- jdk1.8
- <mark>链表长度到8,把链表转成红黑树</mark>
- <mark>树上的数据减少到6,转回成链表</mark>
2 网络
在物理网络的基础上,建立抽象的连接
win + r, 输入 cmd
输入命令:
ipconfig
ping 192.168.21.xxx
<mark>如果ping不通,要关闭防火墙</mark>
开始—搜索防火墙
2.1 Socket 通信 - "套接字"通信
Socket - 插头
Socket - 网络套接字
- 通过 ip 地址,两台主机可以互相找到对象
- 在两台主机上,各选择一个端口号
- 端口是独占的
- <mark>0到1024是一些常见服务的默认端口</mark>
(0000 0000 0000 ~ 0011 1111 1111 )- http 80
- https 443
- ftp 21
- …
- <mark>5万以后,是系统保留端口用,来自动分配</mark>
- <mark>我们选择端口要选择 1024到5万之间的端口号</mark>
2.2 服务器端
被动等待客户端发起连接
ServerSocket 在服务器端,选择一个端口号, 在指定端口上等待客户端发起连接
ServerSocket ss = new ServerSocket(8000);
等待客户端发起连接,建立连接通道,并<mark>返回连接通道的服务器端插头对象</mark>
Socket s = ss.accept();
测试代码
package cn.edut.com.tarena.net;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server1 {
public static void main(String[] args) throws Exception {
int port = 8000 ;
ServerSocket ss = new ServerSocket(port);
System.out.println(port+"端口已经打开...");
//暂停等待客户端连接。客户端连接后,会返回插在服务器端的插头对象。
Socket s = ss.accept();
System.out.println("客户端已连接");
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
/* * 通信内容, * 1.接收 * Hello * 2.返回 * Hi! * Hi! */
for(int i=0 ; i<5 ; i++) {
char c = (char) in.read() ;
System.out.print(c);
}
out.write("Hi!".getBytes("utf-8"));
out.write(Byte.valueOf("Hi!"));
out.flush();//刷出缓存
s.close();
System.out.println("连接断开。");
ss.close();
System.out.println(port+"端口已经关闭。");
}
}
2.3 客户端
主动去连接服务器
Socket s = new Socket(ip, port);
取出双向的流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
2.4 超时
socket.setSoTimeout(毫秒值)
设置接收数据,等待超时时长,超时会出现 SocketTimeoutException
练习1 网络
package day17;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server1 {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8000);
System.out.println(
"服务已经在 8000 端口上启动");
//暂停等待客户端发起连接
System.out.println("等待客户端连接");
Socket s = ss.accept();
System.out.println("客户端已连接");
//从插头对象,获取输入流和输出流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
/* * 通信协议,通信流程,数据格式 * * 服务器端: * 1. 接收 "hello" * 2. 发送 "world" */
for (int i = 0; i < 5; i++) {
char c = (char) in.read();
System.out.print(c);
}
out.write("world".getBytes());
out.flush(); //刷出内存缓存
s.close();//断开连接
ss.close();//停止服务,释放端口
}
}
Client1
package day17;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client1 {
public static void main(String[] args) throws Exception {
Socket s = new Socket("旁边同学ip", 8000);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
/* 客户端: * 1. 发送 "hello" * 2. 接收 "world" */
out.write("hello".getBytes());
out.flush(); //刷出内存缓存
for (int i = 0; i < 5; i++) {
char c = (char) in.read();
System.out.print(c);
}
s.close();
}
}
2.5 阻塞操作
ss.accept()
暂停,等待客户端发起连接
in.read()
对方不发送数据,暂停,死等数据
2.6 服务器端的线程模型
练习2 回声
客户端发送到服务器的数据,原封不动的发回客户端
EchoServer
package day17;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
public void launch() {
new Thread() {
@Override
public void run() {
try {
ServerSocket ss = new ServerSocket(8000);
System.out.println("服务已在 8000 端口上启动");
while(true) {
System.out.println("等待下一个客户端连接");
Socket s = ss.accept();
System.out.println("客户端已连接");
TongXinThread t = new TongXinThread(s);
t.start();
}
} catch (Exception e) {
System.out.println(
"无法在 8000 端口上启动服务,或服务已停止");
}
}
}.start();
}
class TongXinThread extends Thread {
Socket s;
public TongXinThread(Socket s) {
this.s = s;
}
@Override
public void run() {
/* * 通信协议,流程和格式 * UTF-8编码的字符串, * 每段字符串末尾添加换行 * * BR--ISR--网络输入流 * PW--OSW--网络输出流 */
try {
BufferedReader in =
new BufferedReader(
new InputStreamReader(
s.getInputStream(), "UTF-8"));
PrintWriter out =
new PrintWriter(
new OutputStreamWriter(
s.getOutputStream(),"UTF-8"));
String line;
while((line = in.readLine()) != null) {
out.println(line);
out.flush();
}
//断开
} catch (Exception e) {
//断开
}
System.out.println("一个客户端端已断开");
}
}
public static void main(String[] args) {
EchoServer s = new EchoServer();
s.launch();
}
}
EchoClient
package day17;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.Scanner;
public class EchoClient {
public static void main(String[] args) throws Exception {
Socket s = new Socket("找一个人启动服务器", 8000);
BufferedReader in =
new BufferedReader(
new InputStreamReader(
s.getInputStream(), "UTF-8"));
PrintWriter out =
new PrintWriter(
new OutputStreamWriter(
s.getOutputStream(),"UTF-8"));
while(true) {
System.out.print("输入:");
String str = new Scanner(System.in).nextLine();
out.println(str);
out.flush();
String echo = in.readLine();
System.out.println("回声:"+echo);
System.out.println("-----------------");
}
}
}