网页编程 : 关注上层应用
网络编程 : 关注底层数据的传输
IP地址 : 定位网络中的节点...(电脑,手机....)
端口号 : 区分软件
URL : 同一资源定位符
传输层协议 : (标准,合同,规范)
UDP : 邮寄包裹|写信 不安全,协议简单,开销小,效率高 大小限制一般不超过60k
TCP : 打电话 基于连接 安全,效率低 没有大小限制
IP : 定位网络中的节点...(电脑,手机....)
IPV4 4个字节32位 IPV6128位
特殊的IP :
192.168.0.0~192.168.255.255 非注册IP,供组织内部使用的IP
127.0.0.1 本地IP
localhost : 本地
IP 与 域名
DNS解析器 : 做域名与IP直接解析问题
java.net包下:InetAddress
端口 : 件区分软
2个字节 0~65535表示端口号
同一协议下端口号不能冲突
8000称为预留端口号,建议自己设置端口号为8000以上
常见的端口号 :
80 : http
8080 : tomcat
3306 : mysql
1521 : oracle
InetSocketAddress :此类实现IP套接字地址(IP地址+端口号)
Socket : 套接字
传输层为应用层开辟的一个小口子(面向Socket编程,不同的传输层协议对Socket的实现不同)
UDP协议实现 :
两端平等 : 发送端 接口端
UDP协议下数据传输基于字节数组
DatagramSocket
DatagramSocket(int port) 构造一个数据报套接字并将其绑定到本地主机上的指定端口。
void receive(DatagramPacket p) 从此套接字接收数据报包。
void send(DatagramPacket p) 从此套接字发送数据报包。
DatagramPacket : 该类表示数据报包。
UDP协议下基本流程 : 发送端
1.定义发送端
2.准备数据
3.打包
4.发送
5.关闭
//1.定义我是发送端
DatagramSocket sendSocket = new DatagramSocket(9999);
//2.准备数据
byte[] arr = "哈啰".getBytes();
//3.打包
DatagramPacket packet = new DatagramPacket(arr,0,arr.length,new InetSocketAddress("127.0.0.1",8888));
//4.发送
sendSocket.send(packet);
//5.关闭
sendSocket.close();
UDP协议下基本流程 : 接收端
1.定义接收端
2.准备包裹,用来接收数据
3.接收数据
4.处理数据
5.关闭
//1.定义接收端
DatagramSocket receiveSocket = new DatagramSocket(8888);
//2.准备包裹,用来接收数据
byte[] arr = new byte[1024];
DatagramPacket packet = new DatagramPacket(arr,0,arr.length);
//3.接收数据
receiveSocket.receive(packet);
//4.处理数据
//byte[] getData() 返回数据缓冲区。
byte[] newArr = packet.getData();
//int getLength() 返回要发送的数据的长度或接收的数据的长度。
int len = packet.getLength();
System.out.println(new String(newArr,0,len));
//5.关闭
receiveSocket.close();
Tcp协议实现 :
TCP : 基于连接的,类似打电话, 安全,效率低 没有大小限制 基础3次握手建立连接 几次挥手断开连接
协议下两端是不平等的 ,客户端 服务器端
tcp协议下数据传输基于IO流
TCP协议下实现基本流程 :
客户端
1.定义我是客户端 Socket该类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通信的端点。
Socket(String host, int port) 参数ip+端口 指的是服务器的IP+端口
2.准备数据
3.获取输出流,向服务器发送数据
4.刷出
5.关闭
//1.定义客户端
Socket client = new Socket("localhost",8989);
System.out.println("连接建立起来了....");
//2.准备数据
String msg = "good good study,day day up!!!";
//3.获取输出流,向服务器发送数据
DataOutputStream os = new DataOutputStream(client.getOutputStream());
os.writeUTF(msg);
//4.刷出
os.flush();
//5.关闭
os.close();
client.close();
}
服务器端
1.定义我是服务器 ServerSocket该类实现服务器套接字。
2.阻塞式监听
3.获取输入流,读取客户端发送的数据
4.处理数据
5.关闭
//1.定义服务器 ServerSocket
ServerSocket server = new ServerSocket(8989);
//2.阻塞式监听 Socket accept() 侦听对此套接字的连接并接受它。
Socket client = server.accept();
System.out.println("与一个客户端建立连接了.............");
//3.获取输入流,读取客户端发送的数据
DataInputStream is = new DataInputStream(client.getInputStream());
String msg = is.readUTF();
//4.处理数据
System.out.println(msg);
//5.关闭
is.close();
client.close();
server.close();
}
TCP协议下实现双向登录流程 :
客户端
1.定义我是客户端
2.键盘输入接收用户输入的登录信息 username=zhangsan&password=123
3.获取输出流,向服务器发送数据
4.刷出
5.获取输入流,读取服务器响应的结果
6.处理结果
7.关闭
//1.定义客户端
Socket client = new Socket("localhost",8989);
System.out.println("连接建立起来了....");
//2.准备数据
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String username = bf.readLine();
System.out.println("请输入密码:");
String password = bf.readLine();
//3.获取输出流,向服务器发送数据
DataOutputStream os = new DataOutputStream(client.getOutputStream());
os.writeUTF("username="+username+"&password="+password);
//4.刷出
os.flush();
//5.获取输入流,读取服务器响应的结果
DataInputStream is = new DataInputStream(client.getInputStream());
String result = is.readUTF();
//6.处理结果
System.out.println(result);
//7.关闭
is.close();
os.close();
bf.close();
client.close();
服务端
1.定义我是服务器
2.阻塞式监听
3.获取输入流,读取客户端发送的数据
4.处理数据
校验用户输入的登录信息是否正确(admin 1234)
5.获取输出流,将结果响应给客户端
6.刷出
7.关闭
//1.定义服务器 ServerSocket
ServerSocket server = new ServerSocket(8989);
//2.阻塞式监听
Socket client = server.accept();
System.out.println("与一个客户端建立连接了.............");
//3.获取输入流,读取客户端发送的数据
DataInputStream is = new DataInputStream(client.getInputStream());
String msg = is.readUTF();
//4.处理数据
//1)校验方式
/*if("username=admin&password=1234".equals(msg)){
System.out.println("登录成功");
}else{
System.out.println("用户名或密码错误");
}*/
//2)校验方式
String uname=null;
String upwd=null;
String[] arr = msg.split("&");
for(String str:arr){
String[] arr2 = str.split("=");
if("username".equals(arr2[0])){
uname = arr2[1];
}else if("password".equals(arr2[0])){
upwd = arr2[1];
}
}
//5.获取输出流,将结果响应给客户端
DataOutputStream os = new DataOutputStream(client.getOutputStream());
if("admin".equals(uname) && "1234".equals(upwd)){
os.writeUTF("登录成功");
}else{
os.writeUTF("用户名或密码错误");
}
//6.刷出
os.flush();
//7.关闭
os.close();
is.close();
client.close();
server.close();
TCP协议下实现多用户登录流程 :
服务端
服务器端能够实现多多个客户端做响应
重复执行某段代码可以使用循环,但是多个客户端只能排队登录
//1.定义我是服务器 ServerSocket
ServerSocket server = new ServerSocket(8989);
//2.阻塞式监听
boolean flag = true;
while(flag){
Socket client = server.accept();
System.out.println("与一个客户端建立连接了.............");
//3.获取输入流,读取客户端发送的数据
DataInputStream is = new DataInputStream(client.getInputStream());
String msg = is.readUTF();
//4.处理数据
String uname=null;
String upwd=null;
String[] arr = msg.split("&");
for(String str:arr){
String[] arr2 = str.split("=");
if("username".equals(arr2[0])){
uname = arr2[1];
}else if("password".equals(arr2[0])){
upwd = arr2[1];
}
}
//5.获取输出流,将结果响应给客户端
DataOutputStream os = new DataOutputStream(client.getOutputStream());
if("admin".equals(uname) && "1234".equals(upwd)){
os.writeUTF("登录成功");
}else{
os.writeUTF("用户名或密码错误");
}
//6.刷出
os.flush();
//7.关闭
os.close();
is.close();
client.close();
}
server.close();
服务端
利用多线程实现,监听到一个客户端就开启一个线程提供服务
//1.定义服务器 ServerSocket
ServerSocket server = new ServerSocket(8989);
//2.阻塞式监听
boolean flag = true;
while(flag){
Socket client = server.accept();
System.out.println("与一个客户端建立连接了.............");
//开启线程对client提供服务
new Thread(new Channel(client)).start();
}
server.close();
}
static class Channel implements Runnable{
Socket client = null;
DataInputStream is = null;
DataOutputStream os = null;
public Channel(Socket client) {
this.client = client;
try {
is = new DataInputStream(client.getInputStream());
os = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
//读取数据
public String read(){
String msg = null;
try {
msg = is.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
//写出
public void write(String msg){
try {
os.writeUTF(msg);
//6.刷出
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭
public void close(){
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
};
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
};
if(client!=null){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
};
}
@Override
public void run() {
//3.获取输入流,读取客户端发送的数据
String msg = read();
//4.处理数据
String uname=null;
String upwd=null;
String[] arr = msg.split("&");
for(String str:arr){
String[] arr2 = str.split("=");
if("username".equals(arr2[0])){
uname = arr2[1];
}else if("password".equals(arr2[0])){
upwd = arr2[1];
}
}
//5.获取输出流,将结果响应给客户端
if("admin".equals(uname) && "1234".equals(upwd)){
write("登录成功");
}else{
write("用户名或密码错误");
}
//7.关闭
close();