1、什么是网络编程? 在网络通信协议下,不同计算机上运行的程序,进行的数据传输。比如即时通信,网游对战等等。 常见的软件架构: 2、网络编程三要素 IP:设备在网络中的地址
1、什么是网络编程?
在网络通信协议下,不同计算机上运行的程序,进行的数据传输。比如即时通信,网游对战等等。
常见的软件架构:
2、网络编程三要素
IP:设备在网络中的地址,是唯一的标识。
端口号:应用程序在设备中唯一的标识。
协议:数据在网络中传输的规则,常见的协议有:UDP、TCP、http、https、ftp
3、IP
上网设备在网络中的地址,是唯一的。常见的分裂为:ipv4和IPv6
2.1、IPv4
2.2、IPv6
3、InetAddress(java中表示IP的类)
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Test1 {
public static void main(String[] args) throws UnknownHostException {
//获取对象
//IP的对象,确定了IP相当于就确定了一台电脑,所以这里相当于一个电脑对象
final InetAddress qz1027 = InetAddress.getByName("qz1027");
System.out.println(qz1027);
}
}
4、端口号
应用程序在设备中的唯一标识,是由两个字节表示的整数,取值范围为:0 ~ 65535,其中0 ~ 1023的端口被一些特殊的应用占用,注意:一个应用程序只能占用一个端口号。
5、协议
5.1、UDP协议
用户数据协议,是面向无连接的通信协议,速度快,有大小限制,一次最多发送64K,数据不安全,容易丢失。
发送数据
import java.io.IOException;
import java.net.*;
public class Test2 {
public static void main(String[] args) throws IOException {
//创建“快递公司”的对象
DatagramSocket ds = new DatagramSocket();
//打包数据
String str = "你的名字,百度搜不到!";
final byte[] bytes = str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1"); //给本机发送
//端口号
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
//发送数据
ds.send(dp);
//释放资源
ds.close();
}
}
接收数据
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Test3 {
public static void main(String[] args) throws IOException {
//创建“快递公司”的对象
DatagramSocket ds = new DatagramSocket(10086);
//打包数据
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//发送数据,并且这个方法是阻塞的,要等接收到数据后才能结束阻塞态
ds.receive(dp);
//获取端口号
final int port = dp.getPort();
//获取主机名
final InetAddress address = dp.getAddress();
//获取长度
final int length = dp.getLength();
System.out.println("传输过来的数据为:" + new String(bytes, 0, length));
System.out.println("端口号为:" + port + " 数据是从" + address + "电脑中传过来的");
//释放资源
ds.close();
while (true) ;
}
}
5.1.2、udp的三种通信方式:
5.1.2.1、组播:
发送端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
/**
* 组播发送端代码
*
* */
public class Test1 {
public static void main(String[] args) throws IOException {
//创建对象
MulticastSocket ms = new MulticastSocket();
//将数据打包
String str = "你的样子,百度搜不到!";
final byte[] bytes = str.getBytes();
//下面这个发送到的地址要写成组播端口号
InetAddress address = InetAddress.getByName("224.1.0.0");
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
//发送数据
ms.send(dp);
//关闭资源
ms.close();
}
}
接收端:
//接收端1
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
/**
* 组播接收消息 1
*/
public class Test2 {
public static void main(String[] args) throws IOException {
MulticastSocket ms = new MulticastSocket(10086);
//将当前主机添加到224.0.0.1这一组中
InetAddress address = InetAddress.getByName("224.1.0.0");
ms.joinGroup(address);
//创建DatagramPacket的对象
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//接收数据
ms.receive(dp);
//解析数据
System.out.println("发送过来的数据为:" + new String(bytes, 0, dp.getLength()) + " 主机名为:" + dp.getAddress());
//关闭资源
ms.close();
}
}
//接收端2
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
/**
* 组播接收消息 2
*/
public class Test3 {
public static void main(String[] args) throws IOException {
MulticastSocket ms = new MulticastSocket(10086);
//将当前主机添加到224.0.0.1这一组中
InetAddress address = InetAddress.getByName("224.1.0.0");
ms.joinGroup(address);
//创建DatagramPacket的对象
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//接收数据
ms.receive(dp);
//打印数据
System.out.println("发送过来的数据为:" + new String(bytes, 0, dp.getLength()) + " 主机名为:" + dp.getAddress());
//关闭资源
ms.close();
}
}
==运行上面的代码时两个接收端同样会接收到数据。==
广播直接在发送端将下面的代码修改为如下所示即可:
InetAddress address = InetAddress.getByName("255.255.255.255");
5.2、TCP协议
传输控制协议,是面向连接的通信协议,速度慢,没有大小限制,数据安全。它需要在两端各建立一个Socket对象,通信之前要保证连接已经建立。
发送端:
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* TCP协议发送数据
*
* */
public class SendTest {
public static void main(String[] args) throws IOException {
//创建Socket对象
//注意:如果连接不上,代码会报错!!
Socket socket = new Socket("127.0.0.1",10086);
//在连接通道中获取输出流
final OutputStream os = socket.getOutputStream();
//通过流写出数据
os.write("你的样子,百度搜不到!".getBytes());
//释放资源
os.close();
socket.close();
}
}
接收端:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP协议接收数据
*
* */
public class RecieveTest {
public static void main(String[] args) throws IOException {
//创建对象,注意端口号
ServerSocket ss = new ServerSocket(10086);
//监听客户端的连接
Socket socket = ss.accept();
//从连接通道中获取流对象
final InputStream inputStream = socket.getInputStream();
//为了防止中文乱码,我们需要把字节输入流转换为字符输入流,并且使用缓冲流,以提高效率
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
//读取数据
int ch = 0;
while ((ch = br.read()) != -1){
System.out.print((char) ch);
}
//关闭资源
br.close();
ss.close();
}
}
==注意:使用TCP协议时,有三次握手机制来确保连接正常连接,四次挥手机制来确保连接断开,并且数据处理完毕。这样可以避免服务端再还没有来得及处理数据的时候客户端就断开了连接!!==
6、综合练习
6.1、接收并反馈
//发送端
import java.io.*;
import java.net.Socket;
/**
* TCP协议发送数据
*
* */
public class SendTest {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",10086);
//在连接通道中获取输出流
final OutputStream os = socket.getOutputStream();
//通过流写出数据
os.write("你的样子,百度搜不到!".getBytes());
//这里需要给write方法添加一个结束标志,不然接收端就会一直接收通道里面的数据,不会执行反馈逻辑的代码
socket.shutdownOutput();
//接收反馈回来的数据
final InputStream inputStream = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
int ch = 0;
while ((ch = br.read()) != -1){
System.out.print((char) ch);
}
//释放资源
br.close();
socket.close();
}
}
//接收端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP协议接收数据
*
* */
public class RecieveTest {
public static void main(String[] args) throws IOException {
//创建对象,注意端口号
ServerSocket ss = new ServerSocket(10086);
//监听客户端的连接
Socket socket = ss.accept();
//从连接通道中获取流对象
final InputStream inputStream = socket.getInputStream();
//为了防止中文乱码,我们需要把字节输入流转换为字符输入流,并且使用缓冲流,以提高效率
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
//读取数据
int ch = 0;
while ((ch = br.read()) != -1){
System.out.print((char) ch);
}
//反馈数据
final OutputStream outputStream = socket.getOutputStream();
outputStream.write("我滴天,我好感动!".getBytes());
//关闭资源
ss.close();
socket.close();
}
}
6.2、上传文件
//发送端
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class FileSend {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 10086);
//随机生成一个字符串
final String name = UUID.randomUUID().toString().replace("-", "");
System.out.println(name);
//关联本地文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\系统镜像\\Centos7.9\\" + name + ".iso"));
//获取通道
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//定义一个数组
byte[] bytes = new byte[1024];
int len = 0;
//写入数据
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
//传输结束的标志
socket.shutdownOutput();
//获取回馈信息(字节流转字符流然后再转字符缓冲流)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final String s = br.readLine();
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//接收端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class FileReceive {
public static void main(String[] args) {
ServerSocket ss = null;
try {
ss = new ServerSocket(10086);
//监听客户端的连接
final Socket socket = ss.accept();
//关联本地文件(以缓冲流的方式)
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\test\\系统镜像\\CentOS-7-x86_64-DVD-2009.iso"));
//获取缓冲流连接通道
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//定义字节数组
byte[] bytes = new byte[1024];
int len = 0;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
//反馈数据
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功!");
bw.newLine();
bw.flush();
} catch (IOException e) {
try {
ss.close();
} catch (IOException ex) {
e.printStackTrace();
}
}
}
}