目录
网络相关概念与TCP/IP协议
引入
网络相关概念与TCP/IP协议
一,InetAddress类
常用方法
public class Net {
public static void main(String[] args) throws UnknownHostException {
//获取本机InetAddress对象
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
//根据指定主机名获取对象
InetAddress legion = InetAddress.getByName("LEGION");
System.out.println(legion);
//根据域名获取对象
InetAddress baiDu = InetAddress.getByName("www.baidu.com");
System.out.println(baiDu);
//通过InetAddress对象获取对应地址
String hostAddress = localHost.getHostAddress();
System.out.println(hostAddress);
//通过InetAddress对象获取主机名或域名
String hostName = legion.getHostName();
System.out.println(hostName);
}
}
二,Socket
- 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准
- 通信的两端都有Socket,是两台机器间通信的端点
- 网络通信其实就是Socket间的通信
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
- 一般主动发起通信的应用程序为客户端,等待通信请求的为服务端
三,TCP网络编程
- 基于客户端-服务端的网络通信
- 底层使用的是TCP/IP协议
- 基于Socket的TCP编程
===示例(字节流)===
服务端
public class server {
public static void main(String[] args) throws IOException {
//在本机的9999端口监听,等待连接
System.out.println("本机的9999端口,等待连接");
ServerSocket serverSocket = new ServerSocket(9999);
//当没有客户端连接9999时,程序会阻塞,等待连接
//serverSocket可以通过accept方法返回多个socket【多个客户端连接并发】
Socket socket = serverSocket.accept();
System.out.println("服务端socket="+socket.getClass());
System.out.println("连接成功");
//通过socket读取客户端写入数据通道的数据,显示
System.out.print("读取到:");
InputStream inputStream = socket.getInputStream();
byte[] buf=new byte[1024];
int readLen;
while ((readLen=inputStream.read(buf))!=-1){
System.out.println(new String(buf,0,readLen));
}
// socket.shutdownInput();//设置读取终止
//获取输出流
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,client".getBytes());
//关闭流和端口
inputStream.close();
outputStream.close();
socket.close();
serverSocket.close();
System.out.println("服务端退出");
}
}
客户端
public class client {
public static void main(String[] args) throws IOException {
//连接服务端
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
System.out.println("客户端 socket="+socket.getClass());
//连接成功后生成socket,通过socket.getOutPutStream得到跟socket对象关联的输出流
OutputStream outputStream = socket.getOutputStream();
//通过输出流,写入数据到数据通道
outputStream.write("hello,server".getBytes());
System.out.println("写入完成");
socket.shutdownOutput();//设置输入终止
//通过socket读取服务端写入数据通道的数据,显示
System.out.print("读取到:");
InputStream inputStream = socket.getInputStream();
byte[] buf=new byte[1024];
int readLen;
while ((readLen=inputStream.read(buf))!=-1){
System.out.println(new String(buf,0,readLen));
}
//关闭流和端口
outputStream.close();
inputStream.close();
socket.close();
System.out.println("客户端退出");
}
}
===示例(字节流)===
服务端
public class server {
public static void main(String[] args) throws IOException {
//在本机的5467端口监听,等待连接
ServerSocket serverSocket = new ServerSocket(5467);
System.out.println("端口5467 等待连接中");
//当没有客户端连接5467时,程序会阻塞,等待连接
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//serverSocket可以通过accept方法返回多个socket【多个客户端连接并发】
//通过socket读取客户端写入数据通道的数据,显示
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String read = bufferedReader.readLine();
System.out.println(read);
System.out.println("服务端读入完毕");
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("我是服务端,已收到,over");
bufferedWriter.flush();
System.out.println("服务端输入完毕");
bufferedWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();
System.out.println("服务端退出");
}
}
客户端
public class client {
public static void main(String[] args) throws IOException {
//连接服务端
Socket socket = new Socket(InetAddress.getLocalHost(), 5467);
//连接成功后生成socket,通过socket.getOutPutStream得到跟socket对象关联的输出流
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("你好我是客户端,收到请回答");
//使用buffered.newLine也可起到shutDownInput的作用 前提是读取时使用readLine
bufferedWriter.newLine();
//如果使用字符流,需要手动刷新,否则数据不会写入通道
bufferedWriter.flush();
System.out.println("客户端输入完毕");
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String read;
while ((read = bufferedReader.readLine()) != null) {
System.out.println(read);
}
System.out.println("客户端读入完毕");
bufferedReader.close();
bufferedWriter.close();
socket.close();
System.out.println("客户端退出");
}
}
*netstat指令
netstat -an 可以查看当前主机的网络情况,包括端口监听情况和网络连接情况
netstat -an | more 可以分页显示
四,UDP网络编程
1.基本介绍
- 类DatagramSocket和DatagramPacket实现了基于UDP协议网络程序
- UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不保证送达时间
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
2.基本流程
核心的两个类:DatagramSocket和DatagramPacket
建立发送端接收端(没有客户端和服务端的概念 )
发送数据前,建立数据报对象
调用DatagramSocket的发送接收方法
关闭DatagramSocket
===示例===
发送端
public class Sender {
public static void main(String[] args) throws IOException {
//创建包对象,准备发送和接收数据
DatagramSocket socket = new DatagramSocket(9998);//端口与另一端不同
//将需要发送的数据打包
byte[] bytes = "Hello Receiver".getBytes();//发送内容:字节数组
DatagramPacket datagramPacket =
new DatagramPacket(bytes,bytes.length, InetAddress.getByName("LEGION"),9999);//发送目的IP,端口
//发送
socket.send(datagramPacket);
//接收回复
bytes = new byte[64*1024];
datagramPacket = new DatagramPacket(bytes, bytes.length);
socket.receive(datagramPacket);
int length=datagramPacket.getLength();
System.out.println(new String(datagramPacket.getData(),0,length));
//关闭资源
socket.close();
System.out.println("Sender退出");
}
}
接收端
public class Receiver {
public static void main(String[] args) throws IOException {
//创建一个DatagramSocket对象,并设定接收数据的端口
DatagramSocket socket = new DatagramSocket(9999);
//构建一个DatagramPackage对象,作为接收对象
byte[] buf=new byte[64*1024];//UDP传输包最大为64k
DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length);
//接收方法:当有数据包发送到9999端口时,端口会接收,否则阻塞
System.out.println("接收端等待接收数据");
socket.receive(datagramPacket);
//接收到后将数据包拆包,并显示
int length=datagramPacket.getLength();//实际接收到的字节长度
byte[] datagramPacketData = datagramPacket.getData();//拆包
System.out.println(new String(datagramPacketData,0,length));
//回复
buf = "Hello Sender".getBytes();
datagramPacket= new DatagramPacket(buf, buf.length, InetAddress.getByName("LEGION"), 9998);
socket.send(datagramPacket);
//关闭资源
socket.close();
System.out.println("Receiver退出");
}
}