笔记自用 ,来源阳光沙滩:拉大锯
网络模型
网络模型分为:OSI参考模型和TCP/IP参考模型,如下图
用户在应用层里遨游,我们搞开发在传输层和网际层里遨游。简答一点来讲,数据先是从应用层往下走封装打包后,在经过网络层传输到接受端,接收端自下而上拆包,得到用户发送的数据。
网络通信的三要素
IP地址,端口,和传输协议
IP地址,就跟酒店房间号码差不多一个意思。一些特殊的IP地址,本地的:127.0.0.1,主机名:localHost
也可以去DOC命令行 输入ipconfig查看网络配置
在Java中有一个Inet Address类,可以获得IP地址
Inet Address类没有构造方法,无法实例化,采用的是单例设计模式,可以通过它本身的方法拿到对象
import java.net.*;
public class Demo{
public static void main(String[] args)throws Exception{
//获取InetAddress对象
InetAddress ia = InetAddress.getLocalHost();
//获取IP地址
String ip = ia.getHostAddress();
//一步到位
//InetAddress ia = InetAddress.getLocalHost().getHostAddress();
System.out.println("本机IP地址为:"+ip);
}
}
上面的端口指的是是逻辑端口:
1、端口的范围从0~65535(2的16次方减1)
2、系统保留端口为:0~1024
3、一些常用的端口,FTP:21,SMTP:25,HTTP:80
传输协议:UDP和TCP协议(面试常问)
TCP协议 |
---|
说明:是面向连接的协议,要建立连接后在进行传输数据,常用于上传下载 |
是否面向连接:是建立连接,三次握手的机制,友好 |
数据包大小:建立连接后进行大数据传输 |
是否可靠:是,毕竟三次握手 |
特别:一定要先建立连接,速度相比UDP不快 |
关于三次握手:
Client说:服务端哥,我想联你,在吗?—————>请求链接
Server说:客户端弟,我在的,你联过来吧!———->服务端确认链接 Client说:那好,我真的联上来啦!——————–>客户端确认链接
计算机与计算机之间的通信步骤:
1、通过IP地址找到主机;2、通过端口找到接收的程序;3、通过协议发送数据。
UDP
UDP,不面向连接,不可靠,速度快,一般用于聊天等一次性的数据传输,不要精确数据或者永久数据下使用。
在说这两个传输协议之前,要提到的是Socket,Socket大概是插座的意思,那么这里呢可以理解为网线插口,比喻成港口。
如何让两台主机之间传输数据,我们需要一个Socket,也就是一个港口。
UDP的港口是DatagramSocket,它可以接受和发送数据“包”。一般发送的话要指定IP地址,还有端口,而接受端可以不指定IP,但要监视端口。
发送端:
接受端:
下面模拟一个聊天器:
客户端:
//接收端
import java.net.*;
public class Server{
public static void main(String[] args){
//1:创建服务
DatagramSocket ds = null;
DatagramPacket dp = null;
try{
if(ds==null)
ds = new DatagramSocket(10004);
//2:创建缓冲区
byte[] buf = new byte[1024];
//3:接收数据
if(dp==null)
dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
//知道是谁发来的数据
String ip = dp.getAddress().getHostName();
//4:输出数据到控制台上
System.out.println(ip+" :"+new String(buf,
0,
dp.getLength()));
//5:关闭资源
}catch(Exception e){
System.out.println("出问题了!");
}finally{
ds.close();
}
}
}
服务端:
//接收端
import java.net.*;
public class Server{
public static void main(String[] args){
//1:创建服务
DatagramSocket ds = null;
DatagramPacket dp = null;
try{
if(ds==null)
ds = new DatagramSocket(10004);
//2:创建缓冲区
byte[] buf = new byte[1024];
//3:接收数据
if(dp==null)
dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostName();
//4:输出数据到控制台上
System.out.println(ip+" :"+new String(buf,0,
dp.getLength()));
//5:关闭资源
}catch(Exception e){
System.out.println("出问题了!");
}finally{
ds.close();
}
}
}
利用线程多次发送消息:
import java.io.*;
import java.net.*;
public class ChatDemo {
public static void main(String[] args) {
//创建读取线程
new Thread(new ChatThread()).start();
// 创建服务
DatagramSocket ds = null;
BufferedReader br = null;
try {
if (ds == null)
ds = new DatagramSocket();
// 读取键盘录入
if (br == null)
br =
new BufferedReader(new InputStreamReader(System.in));
// 读取数据
String line = null;
while ((line = br.readLine()) != null) {
// 发送数据
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("PresidentsPC"), 9998);
ds.send(dp);
}
} catch (Exception e) {
System.out.println(e.toString());
} finally {
ds.close();
if (br != null)
try {
br.close();
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
//搞一个线程来接受数据
class ChatThread implements Runnable {
public void run(){
while(true){
DatagramSocket ds = null;
try {
ds = new DatagramSocket(9998);//监视9998端口
//获取数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
//获取IP
String ip = dp.getAddress().getHostAddress();
//输出数据
System.out.println(ip+" :"+new String(buf,0,dp.getLength()));
} catch (Exception e) {
System.out.println(e.toString());
}finally{
ds.close();
}
}
}
}
传输协议:TCP
TCP的套路和UDP的差不多,就是客户端的服务是Sokcet,服务端的服务是ServerSocket。
客户端:
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
// 1:创建服务
Socket st = null;
try {
if (st == null)
st = new Socket("PresidentsPC", 13000);
//2:把数据转换成字节数组
byte[] buf = "超前夕第".getBytes();
//获取输出流 发送给服务端
OutputStream out = st.getOutputStream();
//发送数据
out.write(buf);
//关闭发送流
st.shutdownOutput();
//3:获取输入流,获取反馈信息
InputStream in = st.getInputStream();
byte[] buffer = new byte[1024];
int len = in.read(buffer);
//4:打印反馈信息,关闭资源
System.out.println(new String(buffer,0,len));
} catch (Exception e) {
System.out.println(e.toString());
}finally{
if(st!=null){
try{
st.close();
}catch(Exception e)
{
System.out.println(e.toString());}
}
}
}
}
服务端:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args)throws Exception {
//1.创建服务 利用ServerSocket的accept方法
ServerSocket ss = new ServerSocket(13000);
Socket s = ss.accept();
//搞到IP地址
String ip = s.getInetAddress().getHostAddress();
//输出链接上来的机器
System.out.println(ip+"-----connected");
//2:获取输入流
InputStream in = s.getInputStream();
//3:读取数据
byte[] buf = new byte[1024];
int len = 0;
while((len = in.read(buf))!=-1){
//打印到控制台上吧
System.out.println(new String(buf,0,len));
}
s.shutdownInput();
//发送反馈信息
OutputStream out = s.getOutputStream();
out.write("服务端收到啦".getBytes());
//5:关闭资源
s.close();
ss.close();
}
}