网络编程是基于网络进行数据传输,通过IP地址来确定主机在网络中的位置,通过端口号来让计算机和外界进行数据交互。
1.InetSocketAddress类
- 可以代表IP地址和端口号
- 继承抽象类SocketAddress
- 实例代码:
package cn.tedu.test;
import java.net.InetSocketAddress;
public class TestDemo1 {
public static void main(String[] args){
//创建代表IP地址和端口号的对象
//第一个参数代表ip地址
//第二个参数为端口号
//localhost解析成127.0.0.1永远指向本地
InetSocketAddress is=new InetSocketAddress("172.0.0.1",8080);
//获取信息
//获取IP地址
System.out.println(is.getAddress());
//获取主机名
System.out.println(is.getHostName());
//获取端口号
System.out.println(is.getPort());
}
}
2.UDP协议
底层基于流,传输不建立连接,不安全但是速度快
- 底层是根据数据包(64kb)来进行数据传输
- 使用场景:直播、视频、音频等
- 代表UDP的类DatagramSocket
代表数据包的类DatagramPacket - 实例代码:
发送端:
package cn.tedu.test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class TestDemo1 {
public static void main(String[] args) throws IOException {
/*
发送端:
1)创建UDP对象
2)创建数据包(指定IP地址、端口号以及要发送的数据)
3)发送数据包
4)关流
*/
//创建UDP发送端代码
DatagramSocket ds=new DatagramSocket();
//创建数据包对象--准备要发送的数据
//第一个参数代表要发送的数据,byte数组 底层基于字节流
//第二个参数代表实际发送数据的长度
//第三个参数代表IP地址和端口号
DatagramPacket dp=new DatagramPacket("你好".getBytes(),
"你好".getBytes().length,
new InetSocketAddress("127.0.0.1",8080));
//发送数据包
ds.send(dp);
//由于底层基于流实现
//所以需要关流
//关流
ds.close();
}
}
接收端:
package cn.tedu.test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TestDemo2 {
public static void main(String[] args) throws IOException {
/*
接收端
1)创建UDP接收端对象--监听发送端的端口
2)创建数据包对象接收数据
3)接收数据包
4)关流
5)解析数据包
*/
//创建UDP接受端对象--监听发送端的端口
DatagramSocket ds=new DatagramSocket(8080);
//创建数据包对象--用于接收数据
//第一个参数代表存储数据的字节数组
//第二个参数代表实际接收数据的长度
DatagramPacket dp=new DatagramPacket(new byte[1024],1024);
//接收数据
ds.receive(dp);
//关流
ds.close();
//解析数据包
//返回IP地址
System.out.println(dp.getAddress());
//getData--显示接收到的数据
//getLength---展示接收数据的长度
//展示接收的数据
System.out.println(new String(dp.getData(),0,dp.getLength()));
}
}
需要注意的是:需要先启动接收端程序,之后启动发送端代码
- 练习:使用UDP协议以及线程实现一个简易的的聊天室。
package cn.tedu.test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Scanner;
public class TestDemo1 {
public static void main(String[] args) throws IOException {
//创建接收端和发送端线程,启动线程
new Thread(new Recevier()).start();
new Thread(new Sender()).start();
}
}
//定义发送端的类
class Sender implements Runnable{
//代表信息发送过程
@Override
public void run() {
try {
//创建UDP发送端对象
DatagramSocket ds=new DatagramSocket();
//创建Scanner对象
Scanner sc=new Scanner(System.in);
//保证一直能够发送信息
while(true){
//创建存储发送信息的字节数组
byte bs[]=sc.nextLine().getBytes();
//创建数据包对象
DatagramPacket dp=new DatagramPacket(bs,bs.length,
new InetSocketAddress("127.0.0.1",8080));
//发送数据
ds.send(dp);
//不能关流
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//定义接收端的类
class Recevier implements Runnable{
//定义代表接收信息的过程
@Override
public void run() {
//创建代表UDP接收端的对象--监听发送端的端口
try {
DatagramSocket ds=new DatagramSocket(8080);
//创建数据包对象--接收数据
DatagramPacket dp=new DatagramPacket(new byte[1024],1024);
//创建Scanner对象
Scanner sc=new Scanner(System.in);
//保证一直能够发送数据
while(true){
//接收数据
ds.receive(dp);
//解析数据包
System.out.println(dp.getAddress());
System.out.println(new String(dp.getData(),0,dp.getLength()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.TCP协议
- 底层基于流,传输建立连接(三次握手),安全可靠但是传输速度很慢
- 底层基于IO流来进行数据传输,不限制传输数据的大小
- 使用场景:上传和下载、聊天
- Socket 客户端类、ServerSocket 服务器端类
- 实例代码:
客户端
package cn.tedu.net.tcp;
import jdk.internal.util.xml.impl.Input;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TCPClientDemo {
/*
客户端:
1)创建TCP客户端对象
2)建立连接
3)获取自带的字节输出流对象往服务器端写出数据
4)写出数据
5)通知服务器端数据已经发送完毕
6)关流
*/
public static void main(String[] args) throws IOException {
//创建TCP客户端对象
Socket s=new Socket();
//发起连接
s.connect(new InetSocketAddress("127.0.0.1",9092));
//获取自带的字节输出流
//默认往服务器端来传输
OutputStream os=s.getOutputStream();
//写出数据
os.write("下午好".getBytes());
//通知服务器端数据以及发送完毕
s.shutdownOutput();
//从服务器端读取数据
//获取自带字节数计入流
InputStream is=s.getInputStream();
//自建缓冲区---字节数组
byte [] bs=new byte[1024];
int len=-1;
while((len=is.read(bs))!=-1){
//把读取到的内容进行展示
System.out.println(new String(bs,0,len));
}
//通知客户端数据已经接收完毕
s.shutdownInput();
//关流
os.close();
}
}
服务器端:
package cn.tedu.net.tcp;
import jdk.internal.util.xml.impl.Input;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TCPClientDemo {
/*
服务器端:接收数据
1)创建TCP服务器端对象--监听端口
2)接收连接
3)获取自带的字节输入流
4)读取数据
5)通知客户端数据已经读取完毕
6)关流
*/
public static void main(String[] args) throws IOException {
//创建TCP客户端对象
Socket s=new Socket();
//发起连接
s.connect(new InetSocketAddress("127.0.0.1",9092));
//获取自带的字节输出流
//默认往服务器端来传输
OutputStream os=s.getOutputStream();
//写出数据
os.write("下午好".getBytes());
//通知服务器端数据以及发送完毕
s.shutdownOutput();
//从服务器端读取数据
//获取自带字节数计入流
InputStream is=s.getInputStream();
//自建缓冲区---字节数组
byte [] bs=new byte[1024];
int len=-1;
while((len=is.read(bs))!=-1){
//把读取到的内容进行展示
System.out.println(new String(bs,0,len));
}
//通知客户端数据已经接收完毕
s.shutdownInput();
//关流
os.close();
}
}