网络
网络的概念和分类:
网络就是连接在一起共享数据和资源的一组计算机
计算机网络指实现网络通信
按照地理覆盖范围网络可分为局域网,城域网,广域网
局域网(LAN):局限在小的地理区域内或单独的建筑物内
城域网(MAN):覆盖城市或城镇内的广大地理区域
广域网(WAN):实在一个更大的范围内所建立的计算机通信网络,其范围可以超越城市和国家以致全球
网络分层模型:
国际标准化组织(ISO)于1984年颁布了开放系统互连参考模型(OSI)
OSI将网络分为7层:
分层 | 功能 |
---|---|
应用层 | 网络服务和最终用户的接口 |
表示层 | 数据的表示,安全和压缩 |
会话层 | 建立,管理和终止会话 |
传输层 | 定义传输数据斜阳的端口号,流量控制和差错恢恢复 |
网络层 | 进行逻辑地址寻址,实现不同的网络之间的路径选择 |
数据链路层 | 建立逻辑链接,进行硬件地址寻址,差错检验等功能 |
物理层 | 建立,维护,断开物理连接 |
IP地址
IP地址概述
在网络中使用一种具有层次结构的逻辑地址来表示一台主机,这个地址称为IP地址
IP地址目前存在IPV4和IPV6两种标准
IP地址的组成和分类
IP地址的组成
IPV4有32位,由4个8位2进制数组成,每8位之间用圆点隔开,由于2进制不方便记忆所以通常将2进制装换为十进制数来表示,一个IP地址通常有3个点号分开的4个十进制数表示,称为点分十进制
IPV6地址有128位,有8个16位的无符号整数组成,每个整数用4个十六进制数表示,这些数之间用冒号(:)分开。
IP地址的分类
IP地址包含网络地址和主机地址两部分,其中网络地址决定了可以分配的最大网络数,主机地址决定了一个网络中可以存在的最大的计算机的数量
IP地址的网络地址由互联网数字分配机构(IANA)统一分配,IANA将IP地址分为A,B,C,D,E五类,并规定每个类的网络地址和主机地址的长度
A类IP地址:第一组数字表示网络地址,其余三位表示主机地址,A类地址的第一位有效取值范围为1~126
B类IP地址:第两组数字表示网络地址,其余两位表示主机地址,B类地址的第一位有效取值范围为128~191
C类IP地址:第三组数字表示网络地址,其余一位表示主机地址,C类地址的第一位有效取值范围为192~223
D类IP地址:不分网络地址和主机地址,用于组播通信不能在互联网上作为节点地址使用,D类地址的第一位有效取值范围为224~239
D类IP地址:不分网络地址和主机地址,用于科学研究不能在互联网上作为节点地址使用,D类地址的第一位有效取值范围为240~254
特殊IP地址:
0.0.0.0:表示本机
127.0.0.1:表示本机回环地址
255.255.255.255:表示当前子网,一般用于向当前子网广播消息
ServerSocket类
ServerSocket构造方法:
1.接收端口号作为参数创建serversocket对象:ServerSocket s=new ServerSocket(port);
2.接收端口号和最大对列长度作为参数,最大链接长度表示系统在拒绝连接前可以拥有客户端的最大连接数:ServerSocket s=new ServerSocket(port,maxqu);
常用方法:
方法 | 说明 |
---|---|
Socket accept() | 侦听对此套接字的连接并接受它 |
InetAddress getInetAddress() | 返回套接字的本地地址 |
Socket类
Socket对象在客户端和服务器之间建立链接,可用Socket类的构造方法创建套接字,并将此套接字连接至指定的主机和端口。
Socket构造方法:
1.构造方法以主机名和端口号作为来创建一个Socket对象:Socket socket=new Socket(hostName,port);
2.以InetAddress对象和端口号作为参数来创一个Socket对象:Socket socket=new Socket(address,port);
常用方法:
方法 | 说明 |
---|---|
InetAddress getInetAddress() | 返回与socket对象关联的inetaddress(地址) |
int getport() | 返回此socket对象所连接的远程端口 |
int getLocalPort() | 返回此socket对象所连接的本地端口 |
InputStream getInputStream() | 返回与此套接字关联的InputStream |
OutputStream getOutputStream() | 返回与此套接字关联的OutputStream |
void ShutdownInput() | 将此套接字的输入流放在“流结束” |
void ShutdownOutput() | 禁用此套接字的输出流 |
服务器示例:
public class TcpSerer {
public static void main(String[] args) {
String s="响应";
try {
//构建serversocket对象
ServerSocket serverSocket=new ServerSocket(8888);
System.out.println("服务器已启动,监听中.......");
//阻塞服务器,等待客户端端发送数据
Socket socket=serverSocket.accept();
//构建输入流接收客户端发送的数据
InputStream is=socket.getInputStream();
byte[] bytes=new byte[1024];
int len;
while ((len=is.read(bytes))!=-1){
//打印
System.out.println("客户端:"+new String(bytes,0,len));
}
//响应客户端
OutputStream os=socket.getOutputStream();
os.write(s.getBytes());
os.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端示例:
public class TcpClient {
public static void main(String[] args) {
try {
//创建socket对象用于向客户端发送消息
Socket socket=new Socket("127.0.0.1",8888);
//构建输出流
OutputStream os=socket.getOutputStream();
//向服务器发送数据
os.write("你好服务器".getBytes());
//禁用套接字的输出流
socket.shutdownOutput();
//构建输入流接收服务器的响应消息
InputStream is =socket.getInputStream();
byte[] bytes=new byte[1024];
int len;
while ((len=is.read(bytes))!=-1){
System.out.println("客户端响应信息为:\n"+new String(bytes,0,len));
}
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
传输对象服务端示例:
public class userServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8848);
System.out.println("服务器已启动...");
Socket socket=serverSocket.accept();
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
user user=(user) ois.readObject();
System.out.println(socket.getInetAddress()+"客户端发送:姓名:"+user.getName()+",年龄:"+user.getAge());
//响应客户端
OutputStream os=socket.getOutputStream();
os.write("成功接收!".getBytes());
os.close();
ois.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
传输对象客户端示例:
public class userClient {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.print("请输入姓名:");
String name =input.next();
System.out.print("请输入年龄:");
String age =input.next();
try {
Socket socket=new Socket("127.0.0.1",8848);
ObjectOutputStream oos=new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(new user(name,age));
System.out.println("发送成功!");
socket.shutdownOutput();
InputStream is=socket.getInputStream();
byte[] bytes=new byte[1024];
int len;
while ((len=is.read(bytes))!=-1){
System.out.println("服务器:"+new String(bytes,0,len));
}
is.close();
oos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
多线程处理:
public class userServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8848);
System.out.println("服务器已启动...");
while (true){
Socket socket=serverSocket.accept();
new userServer_server(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Server_test extends Thread{
Socket socket;
public Server_test() {
}
public Server_test(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
Scanner input=new Scanner(System.in);
try {
InputStream is=socket.getInputStream();
byte[] bytes=new byte[1024];
int len;
while ((len=is.read(bytes))!=-1){
System.out.println("客户端:"+new String(bytes,0,len));
}
OutputStream os=socket.getOutputStream();
System.out.print("回复:");
String out=input.next();
os.write(out.getBytes());
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP和UDP的区别:
1.Tcp面向链接Udp是无连接的,即发送数据之前不需要建立链接
2.TCP提供可靠的服务,也就是说通过TCP链接传送的数据,无差错,不丢失,不重复,且按序到达,upd尽最大努力交付
3.TCP面向字节流,实际上是TCP数据看成一连串无结构的节流,Udp是面向报文的,udp没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低
4.每一条TCP链接只能是点到点的,udp支持一对一,一对多,多对一和多对多的交互通信
5.TCP首部开销20字节,udp的内部开销小,只有8个字节
6.TCP的逻辑通信信道是全双工可靠信道,udp则是不可信信道
基于UDP协议的Socket编程
DatagramSocket类用于发送或接收,DatagramPacket类不提供发送或接收数据的方法,而DatagramSocket类提供的send()和receive()方法 用于通过套接字发送和接收数据
Datagrampacket类
构造方法:
方法 | 说明 |
---|---|
DgramPacket(byte[] data,int size) | 构建DatagramPacket对象,封装长度为size的数据包 |
DatagramPacket(byte[] buf,int length,InetAddress address,int port) | 构建DatagramPacket对象并发送到指定主机,端口号 |
常用方法:
方法 | 说明 |
---|---|
byte[] getData() | 返回字节数组,该数组包含接收到或要发送的数据报中的数据 |
int getlength() | 返回发送或接收的数据的长度 |
InetAddress getAddress () | 返回接收或发送的数据报的主机的IP地址 |
int getport() | 返接收或发送的此数据报的主机的端口号 |
DatagramSocket类
构造方法
方法 | 说明 |
---|---|
DatagramSocket() | 构建DatagramSocket对象,并将其与本地主机上的任何可用的端口绑定 |
DatagramSocket(int port) | 创建DatagramSocket对象,并将其与本地主机上的指定端口绑定 |
常用方法
方法 | 说明 |
---|---|
void connect(Inet Address address,int port) | 将当前DatagramSocket对象链接到远程地址的指定地址 |
void close() | 当前的DatagramSocket对象 |
void disconnect() | 断开datagramsocket对象的链接 |
int getLocaPort() | 返回当前DatagramSocket对象绑定的主机的端口号 |
void send(Datagrampacket p) | 发送指定的数据报 |
void receive(Datagrampacket p) | 接收数据报,收到以后存放在指定的Datagrampacket对象中 |
UDP协议客户端示例:
public class UdpClient {
public static void main(String[] args) {
try {
//创建链接对象
DatagramSocket ds=new DatagramSocket();
String msg="我是客户端!";
//包装数据包
DatagramPacket dp=new DatagramPacket(msg.getBytes(),msg.getBytes().length, InetAddress.getByName("192.168.0.167"),8888);
//发
ds.send(dp);
//接收
byte[] bytes=new byte[1024];
dp=new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
//解析数据,打印数据
System.out.println(new String(dp.getData(),0,dp.getLength()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP协议服务器示例:
public class UdpServer {
public static void main(String[] args) {
try {
//构建Datagramsocket对象
DatagramSocket ds=new DatagramSocket(8888);
//创建空数据包
byte[] bytes=new byte[1024];
//包装数据包用于接收数据
DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
//接收
ds.receive(dp);
//解析数据,打印数据
System.out.println(new String(dp.getData(),0,dp.getLength()));
String msg="我是服务器!";
//getSocketAddress()返回指定DatagramPacket对象的地址和端口
DatagramPacket dp2=new DatagramPacket(msg.getBytes(),msg.getBytes().length,dp.getSocketAddress());
//发送
ds.send(dp2);
System.out.println("发送成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}