java.net.*
Ipv4:32位//点分十进制
ipv6:128位
域名:通过域名在DNS服务器找IP
公网IP:192.168.0.0-192.168.255.255
本机IP:127.0.0.1
ipconfig:查看本机IP
ping IP地址:检查网络是否连通
InetAddress类
表示IP地址
方法:
获取本机IP:getLocalHost()
根据IP地址或者域名返回InetAddress对象:getByName(String)
获取IP对应主机号:getHostName()
获取IP地址对象中的IP地址:getHostAddress()
指定毫秒内,判断主机与该IP对应的机器是否连接:isReachable()
标记在计算机设备上运行的应用程序
16位二进制,0-65535之间
分类:
周知端口:0-1023,知名应用占用
注册端口:1024-49151,用户进程或某些应用程序
动态端口:49152-65535,不分配给特定进程,动态分配
自己开发的程序用注册端口
不能有两个进程端口号一样
规定的连接规则,以及数据传输标准
国际标准:
OSI
实际应用比较广的:
TCP/IP网络模型
应用层:
HTTP、FTP、SMTP
传输层:
UDP(用户数据报协议):
无连接、不可靠
自己IP、端口、目的IP、目的端口、数据
效率高
场景:
语音通话、视频直播
TCP(传输控制协议):
面向连接、可靠通信
保证数据可靠:
三次握手连接
传输数据进行确认
四次握手断开连接
全双工(双方收发)
网络层:
IP
数据链路层:
ARP
java.net.DatagramSocket
客服端
服务端
创建:
创建客户端,随机分配端口号:DatagramSocket()
创建服务端,指定端口号:DatagramSocket(int port)
方法:
发数据包:send()
使用数据包接收数据:receive()
创建数据包:
DatagramPacket类
发出数据包:DatagramPacket(byte[],length,InetAdress,port)
接收数据包:DatagramPacket(byte[],length)
获取数据包实际收到的字节个数:getLength()
注意:用完要close关闭
放在死循环中
java.net.Socket类
客服端:Socket(host,port)
获取字节输入流:getInputStream
获取字节输出流:getOutputStream
服务端:
ServerSocket(int port)
方法:accept()//等待获取客户端连接,返回Socket对象(客户端的)
注意:监听端口并不用于传输数据,而是负责监听连接请求。
放死循环
多线程
聊天室:
简略实现:
package com.chatwindow.www;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client{
public static void main(String[] args) throws Exception {
Scanner sc=new Scanner(System.in);
Socket socket=new Socket("127.0.0.1",8888);
OutputStream ps=socket.getOutputStream();
DataOutputStream ds=new DataOutputStream(ps);
new Thread(new ClientRunnable(socket)).start();
System.out.print("请输入用户名:");
String msg=sc.nextLine();
ds.writeUTF(msg);
while(true){
msg=sc.nextLine();
if(msg.equals("exit")){
System.out.println("欢迎下次光临!");
ds.close();
socket.close();
break;
}
ds.writeUTF(msg);
}
}
}
package com.chatwindow.www;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class ClientRunnable implements Runnable{
private Socket socket;
public ClientRunnable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
InputStream is= null;
try {
is = socket.getInputStream();
} catch (Exception e) {
throw new RuntimeException(e);
}
DataInputStream di=new DataInputStream(is);
while(true){
try {
String msg=di.readUTF();
System.out.println(msg);
} catch (IOException e) {
System.out.println("再见");
break;
}
}
}
}
package com.chatwindow.www;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
public static List<Socket> list=new ArrayList<>();
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888);
System.out.println("服务器已经启动!");
while(true){
Socket socket = ss.accept();
list.add(socket);
ServersRunnable sr = new ServersRunnable(socket);
new Thread(sr).start();
}
}
}
package com.chatwindow.www;
import javax.xml.crypto.Data;
import java.io.*;
import java.net.Socket;
public class ServersRunnable implements Runnable{
Socket socket;
public ServersRunnable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
InputStream is= null;
try {
is = socket.getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
DataInputStream ds=new DataInputStream(is);
String name="";
try {
name=ds.readUTF();
for(Socket socket:Server.list){
OutputStream os=socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
dos.writeUTF(name+":恭喜您登录成功!");
dos.flush();
}
System.out.println(name+":恭喜您登录成功!");
} catch (IOException e) {
return ;
}
while(true){
try {
String msg=ds.readUTF();
for(Socket socket:Server.list){
OutputStream os=socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
dos.writeUTF(name+":"+msg);
dos.flush();
}
System.out.println(msg);
} catch (Exception e) {
System.out.println(name+"用户下线了!");
Server.list.remove(socket);
try {
ds.close();
socket.close();
} catch (Exception ex) {
System.out.println("服务器已关机");
break;
}
break;
}
}
}
}
BS架构一定要满足HTTP协议
格式:
HTTP/1.1 200 OK
Content-Type:text/html;charst=UTF-8
空行
内容
package com.BS.www;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket=new ServerSocket(8080);
System.out.println("服务器启动成功");
while(true){
Socket socket=serverSocket.accept();
new Thread(new Myserver(socket)).start();
}
}
}
package com.BS.www;
import jdk.net.Sockets;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
public class Myserver implements Runnable{
private Socket socket;
public Myserver(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try (OutputStream os = socket.getOutputStream()) {
PrintStream ps=new PrintStream(os);
ps.println("HTTP/1.1 200 OK");
ps.println("Content-Type:text/html;charset=UTF-8");
ps.println();
ps.println("我爱你中国");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
每次新开线程好不好:
不好
高并发容易崩溃
解决:线程池
package com.BS.www;
import com.zsy.www.MyRunnable;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket=new ServerSocket(8080);
System.out.println("服务器启动成功");
ThreadPoolExecutor tpe=new ThreadPoolExecutor(
16*2,//IO设置为CPU数量二倍
16*2,
60L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(20),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
while(true){
Socket socket=serverSocket.accept();
tpe.execute(new Myserver(socket));
}
}
}