1.TCP/IP协议
TCP:传输控制协议
IP:网络地址协议
应用层常见协议
HTTP:超文本传输协议
Telnet:远程登录协议
SSH:远程登录协议(保证安全)
传输层协议
打包和确定目的应用程序
TCP保证数据的可靠有序, UDP 不保证
http 占用 80 端口
telnet 占用 22 端口
ssh 占用 22 端口
mysql 占用 3306 端口
互联网层协议
IP协议
网络访问层
连接: telnet 对方 ip 端口号
发送请求: http协议
请求:
GET /index.html HTTP/1.1
Host: localhost
回车
回车
响应:
HTTP/1.1 200
2.各种客户端
Socket :
传输层 TCP 协议
创建Scoket new Socket(“ip地址”, 端口号);
socket.getOutputStream(); // 发数据
socket.getInputStream(); // 收数据
URL :
创建 new URL(“http://ip地址:端口/资源地址”)
HTTPURLConnection conn = url.openConnection(); // 建立连接, 发送get请求
conn.getInputStream(); // 拿到服务器返回的结果
3. 服务器端
3.1 阻塞IO BIO blocking
ServerSocket 服务器的端点
new ServerSocket(端口号); // 每个程序只能占用一个端口, 自己的程序用4位以上的端口
.accept(); // 等待, 直到客户端连接为止
new Thread(new Runnable(){
public void run() {
// 把io相关的操作放在线程内执行,让每个线程处理一个io操作,避免io阻塞
}
}).start();
阻塞io的特点,一个socket执行io读写操作会阻塞其它io的读写
一个线程内io的读写是串行的,可以用多线程的方法来解决, 建议使用线程池而不是自己手动创建线程
3.2 并发量再高怎么办
非阻塞IO NIO, nonBlocking IO, new IO
线程(多路)复用
一个线程可以同时处理多个io操作, 减少了线程的数量,能够应付更高的并发
WEB服务器 tomcat 雄猫(BIO,NIO)
Netty 服务器, 封装了NIO技术,并发能力很高
spark 分布式计算框架
Redis 缓存服务器 (C) 单线程 QPS 10万
3.3lambda表达式
new Thread(new Runnable(){
public void run(){}
}).start();
new Thread(()->{}).start();
参数部分 特殊符号 代码体
( 形参 ) -> { 执行的代码 }
针对单方法的接口,才能使用lambda表达式简化
()->{}
参数部分可以省略类型, 如果代码体部分只有一条语句,{} 也可以省略,且不能加;号
如果代码体部分 只有一条语句,那么它还可以充当返回值,从而省略return
利用Socket实现简单的群聊功能
服务端
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(4396);
System.out.println("服务器已经启动...");
ExecutorService threadPool = Executors.newCachedThreadPool();
ConcurrentHashMap<Socket, SocketAddress> map = new ConcurrentHashMap<>();
while (true){
Socket accept = serverSocket.accept();
SocketAddress address = accept.getRemoteSocketAddress();
System.out.println(address+"已经连接...");
map.put(accept,address);
threadPool.submit(() -> {
try {
//handle(accept);
InputStream in = accept.getInputStream();
while (true) {
byte[] bytes = new byte[1024 * 8];
int len = in.read(bytes);
if (len == -1) {
break;
}
String s = new String(bytes, 0, len);
for (Socket socket : map.keySet()) {
OutputStream out = socket.getOutputStream();
out.write(s.getBytes());
}
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
}
客户端
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 4396);
OutputStream out = socket.getOutputStream();
System.out.println("请输入你的昵称:");
Scanner sc = new Scanner(System.in);
String name = sc.next();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println("请输入你发送的信息:");
String msg = sc.next();
try {
out.write((name+"说:"+msg).getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
InputStream in = socket.getInputStream();
while (true){
byte[] bytes = new byte[1024];
int len=in.read(bytes);
if (len==-1){
break;
}
String string = new String(bytes,0,len);
System.out.println(string);
}
}
}