网络编程
相互连接的计算机 交换数据 共享资源
网络编程三要素:IP地址,设备标识;端口,应用程序的标识;协议(UDP用户数据报协议和TCP传输控制协议)
IP地址:
概述
IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。
唯一标识网络上的每一台计算机
组成:32位,由4个8位二进制组成
IP地址的组成
- IP地址 = 网络地址 + 主机地址
- 网络地址:表示计算机或网络设备所在的网段
- 主机地址:标识特地主机或网络设备
其中A、B、C3类(如下表格)由InternetNIC在全球范围内统一分配,D、E类为特殊地址。D类用于组播通信;E类用于科研
类别 | 最大网络数 | IP地址范围 | 单个网段最大主机数 | 私有IP地址范围 |
---|---|---|---|---|
A | 126(2^7-2) | 1.0.0.1-127.255.255.254 | 16777214 | 10.0.0.0-10.255.255.255 |
B | 16384(2^14) | 128.0.0.1-191.255.255.254 | 65534 | 172.16.0.0-172.31.255.255 |
C | 2097152(2^21) | 192.0.0.1-223.255.255.254 | 254 | 192.168.0.0-192.168.255.255 |
IP地址的配置和检测
- 查看本机的IP地址:ipconfig
- 测试网络是否连接:ping 目标IP地址
- 127.0.0.1:是送回地址,可以代表本机地址,用来测试使用
InetAddress的使用
- static InetAddress getByName(String host):确定主机名称的地址,主机名称可以是机器名称,也可以是IP地址
- String getHostName():获取此IP地址的主机名
- String getHostddress():返回文本显示IP地址字符串
- static InetAddress getLocalHost( ) :返回表示本地主机InetAddress对象
- static InetAddress[] getAllByName(String hostName) 为主机名为hostName的所有可能主机返回InetAddress对象组
public static void main(String[] args) throws Exception {
InetAddress address = InetAddress.getByName("192.168.226.176");
String name = address.getHostName();
String ip = address.getHostAddress();
System.out.println("主机名:"+name);
System.out.println("IP地址:"+ip);
}
DNS域名解析
DNS:Domain Name System,域名系统
网络服务器
- 通常指在网络环境下,具有较高计算能力,能够提供用户服务功能的计算机
网络通信协议
为了在网络中不同的计算机之间进行通信而建立的规则、标准或约定的集合
三要素:
- 语义,解释控制信息每个部分的意义。它规定了需要发出何种控制信息,以及完成的动作与做出什么样的响应。
- 语法,用户数据与控制信息的结构与格式,以及数据出现的顺序。
- 时序,对事件发生顺序的详细说明。
接收数据—>断分 二进制01—>转换10进制—端口号—>提供服务
–应用层(application layer)
·专门针对某些应用提供服务
–传输层(transportlayer)
·网络层只把数据送到主机,但不会送到进程。传输层负责负责进程与主机(host)间的传输,主机到主机(host-to-host)的传输交由网络层负责–传输层也称为端到端送
–网络层(network layer)
·把包里面的目的地址拿出来,进行路由选择(routing),决定要往哪个方向传输
·负责从源(source)通过路由选择到目的地(destination)的过程,达到从源主机传输数据到目标主机的目的(host-to-host)
–数据链路层(data-link layer)
·通过物理网络传送包(package)–这里的包是通过网络层交过来的数据报(datagram)
·只完成一个节点到另一个节点的传送(单跳)(hop-by-hop, node-to-node)
–物理层(physicallayer)
·通过线路(可以是有形的线也可以是无线链路)传送原始的比特(bit)流
·只完成一个节点到另一个节点的传送(单跳)
- 某公司使用一台路由器,将公司的50台计算机连接在一起,构成的是:局域网
- 网络中有一台主机,IP地址是210.10.8.1,它的网络ID是:210.10.8
套接字Socket:
https://baike.baidu.com/item/%E5%A5%97%E6%8E%A5%E5%AD%97/9637606?fromtitle=socket&fromid=281150&fr=aladdin
概述
Socket的底层机制复杂,Java平台提供了一些简单的API(应用程序编程接口),可以更简单有效的使用Socket开发而无需了解底层机制
- 通信链路的端点就被称为“套接字”(Socket)
- 是提供给应用程序的接口
java.net包
Socket、ServerSocket、DatagramPacket、DatagramSocket、InetAddress
……
基于TCP协议的Socket编程
-
基于TCP协议的Socket编程
用来实现双向安全连接网络通信
-
Socket通信模型
进行网络通信时,Socket需要借助数据流来完成数据的传递工作
-
Socket网络编程一般可以分成如下步骤进行:
- 建立连接【网络编程模型:客户端/服务器(C/S)】
- 打开Socket关联的输入输出流
- 数据流中读写信息
- 关闭所有的数据流和Socket
Socket中实现对象的传递实例:
-
传递对象 序列化
ObjectOutputStream oos = new ObjectOutputStream(…); oos.writeObject(…); ObjectInputStream ois = new ObjectInputStream(…); Object = ois.readObject();
/**
* Socket中实现对象的传递
* 序列化
* 用户对象
* @author Lenovo
*
*/
public class UserVO implements Serializable{
private String name;
private String pwd;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
/**
* 客户端序列化
* @author Lenovo
*
*/
public class UserClient {
public static void main(String[] args) {
System.out.println("----客户端----");
try {
Socket socket = new Socket("localhost",8000);
OutputStream os= socket.getOutputStream();
UserVO userVO = new UserVO();
userVO.setName("张安");
userVO.setPwd("00000");
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(userVO);
//得到服务端的回复
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String info = null;
while((info=br.readLine())!=null){
System.out.println("服务端说:"+info);
}
os.close();socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 服务端序列化
* @author Lenovo
*
*/
public class UserServer {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("----服务端-----");
try {
ServerSocket serverSocket = new ServerSocket(8000);
Socket sk = serverSocket.accept();
InputStream is = sk.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
UserVO user = (UserVO) ois.readObject();
System.out.println("客户端说---账号是"+user.getName()+",密码是"+user.getPwd());
//服务端反向回复客户端:
String msg = "登录成功"+user.getName()+"欢迎您的登录!!!";
OutputStream os = sk.getOutputStream();
os.write(msg.getBytes());
//释放资源
ois.close();
is.close();
sk.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
基于UDP协议的Socket编程
编码时:TCP在连接建立时双方存在主次之分;UDP通信双方完全平等
TCP | UDP | |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠 | 不可靠 |
速度 | 慢 | 快 |
步骤:
- 利用 DatagramPacket 对象封装数据包
- 利用 DatagramSocket 发送数据包:ds.send()
- 利用 DatagramSocket 接收数据包:ds.receive()
- 利用 DatagramPacket 处理数据包
UDP实例:
实现客户咨询问题,客服人员答复问题
咨询时,客户是发送方,客服人员是接收方
答复时,客服人员是发送方,客户是接收方,实现思路和咨询时相同
/**
* 客户
* @author 왕샤오옌
*
*/
public class LoginClient {
public static void main(String[] args) {
System.out.println("-------张三先发问者------");
Scanner sc = new Scanner(System.in);
DatagramPacket dp = null;
DatagramSocket ds = null;
InetAddress is;
try {
is = InetAddress.getByName("127.0.0.1"); //不放循环
while(true){
System.out.print("张三请输入:");
String words = sc.next();
//封装数据包
dp = new DatagramPacket(words.getBytes(),words.getBytes().length,is,5000);
//创建发送接口对象
ds = new DatagramSocket();
ds.send(dp);
//接收信息:
byte[] info = new byte[1024];
dp = new DatagramPacket(info,info.length); //创建数据包,只要两个参数
ds.receive(dp); //将用户发来的信息,放入数据包
String massage = new String(dp.getData()); //得到数据
System.out.println("李四:"+massage);
//关闭发送端
ds.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 客服
* @author 왕샤오옌
*
*/
public class LoginServer {
public static void main(String[] args) {
System.out.println("-------李四回答者------");
Scanner sc = new Scanner(System.in);
DatagramPacket dp = null;
DatagramSocket ds = null;
try{
ds = new DatagramSocket(5000); //传一个端口号
while(true){
//李四接收张三发来的:
byte[] info = new byte[1024];
dp = new DatagramPacket(info,info.length); //已经有dp了
ds.receive(dp);
String massage = new String(dp.getData());
System.out.println("张三:"+massage);
//数据包从哪里来:23行dp
SocketAddress sa = dp.getSocketAddress(); //得到地址和端口号
//李四发送
System.out.println("李四请输入:");
String words = sc.next();
dp = new DatagramPacket(words.getBytes(),words.getBytes().length,sa);
ds.send(dp);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
总结