网络编程三要素
- IP地址:网络中某一台设备的唯一标识
ip地址分为:ipv4和ivp6
ivp4:用4组8个二进制数表示 如
192.168.0.1
ivp6:用8组16个二进制数表示 如:
2001.0db8.3c4d.0015.0000.0000.12af.1a2b
- 端口号:设备中应用程序的标识
端口号的范围: 0~65535
常用端口号: 8080(tomcat服务器的端口号)、80(网络通信的默认端口号)、3306(Mysql数据库的端口号)
注意:操作系统中已经使用了一些端口号(0~1024)被使用,我们尽量选择1024之后的端口号
- 协议:网络通信的规则
UDP:面向无连接不可靠的网络协议(不靠谱,效率高) 音频 视频传输
Tcp:面向有连接的可靠的网络协议(靠谱、效率低)文件上传、文件下载
UDP通信
发送端
1.创建DatagramSocket对象(邮局)
2.创建数据包DatagramPacket对象(打包裹)
3.发送数据包send方法
4.释放资源close
//1.创建DatagramSocket对象(邮局)
DatagramSocket ds=new DatagramSocket();
//2.创建数据包DatagramPacket对象(打包裹)
byte[] bs="helloworld".getBytes();
String ip="127.0.0.1"; //127.0.0.1是一个本机的地址,发送的目的地为本机
int port=10086;
DatagramPacket dp=new DatagramPacket(bs,bs.length,InetAddress.getByName(ip),port);
//3.发送数据包send方法
ds.send(dp);
//3.发送数据包send方法
ds.send(dp);
接收端
1.创建DatagramSocket对象邮局(邮局) 指定端口号
2.创建数据包DatagramPacket对象(空包裹)
3.发送数据包receive方法
4.解析数据包(拆包裹)
5.释放资源close
//1.创建DatagramSocket对象 指定端口号
DatagramSocket ds=new DatagramSocket(10086);
//2.接受数据包
byte[] bs=new byte[1024];
DatagramPacket dp=new DatagramPacket(bs,bs.length);
ds.receive(dp); //阻塞
//3.拆包
//获取包中的数据
byte[] data = dp.getData();
//获取数据的有效长度
int length = dp.getLength();
//把字节数组转换为字符串
String str=new String(data,0,length);
System.out.println(str);
//4.释放资源
ds.close();
TCP通信
想要完成TCP通信就需要有客服端程序和服务端程序。
TCP客服端
public class Client {
public static void main(String[] args) throws IOException {
//创建Socket对象,绑定服务端的ip地址 和 端口号
//如果服务端存在,则就可以建立连接
Socket socket=new Socket("127.0.0.1",10010);
//获取输出流对象,输出目的网络
OutputStream out = socket.getOutputStream();
out.write("hello".getBytes());
//获取输入流,读取服务端回写的数据
InputStream in = socket.getInputStream();
byte[] bs=new byte[1024];
int len=in.read(bs);
//把读取到的有效字节个数转换为字符串
String str=new String(bs,0,len);
System.out.println("服务端返回数据:"+str);
//释放资源
socket.close();
}
}
TCP服务端
public class Server {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象,绑定程序的端口号10010
ServerSocket ss=new ServerSocket(10010);
//监听客户端
Socket s = ss.accept(); //阻塞,等待客户端过来连接
//获取输入流对象
InputStream in = s.getInputStream();
byte[] bs=new byte[1024];
int len = in.read(bs);
//把读取到的有效字节个数转换为字符串
String str=new String(bs,0,len);
System.out.println("客户端发过来的数据:"+str);
//获取输出流对象,往客户端回写数据
OutputStream out = s.getOutputStream();
out.write("你好".getBytes());
//释放资源
s.close();
}
}
文件上传
客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建Socket对象,绑定服务端的ip地址 和 端口号
//如果服务端存在,则就可以建立连接
Socket socket=new Socket("127.0.0.1",10010);
//获取输出流对象,输出目的网络
OutputStream out = socket.getOutputStream();
//把一个a.txt文件中的数据发送到服务端
File file = new File("day12-code/itheima20.jpg");
FileInputStream fis=new FileInputStream(file);
//一边读一边写
byte[] bytes=new byte[1024];
int len;
while ((len=fis.read(bytes))!=-1){
out.write(bytes,0,len);
}
//写结束标记,告诉服务端我的数据写完了
socket.shutdownOutput();
fis.close();
//获取输入流,读取服务端回写的数据
InputStream in = socket.getInputStream();
byte[] bs=new byte[1024];
len=in.read(bs);
//把读取到的有效字节个数转换为字符串
String result=new String(bs,0,len);
System.out.println("服务端返回数据:"+result);
//释放资源
socket.close();
}
}
服务端
public class Server {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象,绑定程序的端口号10010
ServerSocket ss=new ServerSocket(10010);
//监听客户端
Socket s = ss.accept(); //阻塞,等待客户端过来连接
//获取输入流对象
InputStream in = s.getInputStream();
//写入文件的流,用来把读取到的数据保存到文件中
//生成一个文件
long time = System.currentTimeMillis();
String filename="itheima"+time+".jpg";
//用于往服务端的文件中写如数据
FileOutputStream fos=new FileOutputStream("/Users/wangqi/Desktop/upload/"+filename);
//读取客户端发过来的数据
byte[] bs=new byte[1024];
//先读取一次,获取文件名称
int len;
while ((len=in.read(bs))!=-1){
//String str = new String(bs, 0, len);
//把读取到的数据,往服务端的文件中写
fos.write(bs,0,len);
}
//获取输出流对象,往客户端回写数据
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
//释放资源
s.close();
}
}
文件上传(多线程)
客户端
public class Client {
public static void main(String[] args) throws IOException {
//创建Socket对象,绑定服务端的ip地址 和 端口号
//如果服务端存在,则就可以建立连接
Socket socket=new Socket("127.0.0.1",10086);
//获取输出流对象,输出目的网络
OutputStream out = socket.getOutputStream();
//把一个a.txt文件中的数据发送到服务端
File file = new File("day12-code/itheima15.jpg");
FileInputStream fis=new FileInputStream(file);
//一边读一边写
byte[] bytes=new byte[1024];
int len;
while ((len=fis.read(bytes))!=-1){
out.write(bytes,0,len);
}
//写结束标记,告诉服务端我的数据写完了
socket.shutdownOutput();
fis.close();
//获取输入流,读取服务端回写的数据
InputStream in = socket.getInputStream();
byte[] bs=new byte[1024];
len=in.read(bs);
//把读取到的有效字节个数转换为字符串
String result=new String(bs,0,len);
System.out.println("服务端返回数据:"+result);
//释放资源
//socket.close();
}
}
服务端
服务端可以为多个Socket提供上传文件服务,当监听到一个Socket连接过来就为其开一条线程,执行上传文件的代码
- 上传文件任务(UploadRunnable)
public class UploadRunnable implements Runnable {
private Socket s;
public UploadRunnable(Socket s) {
this.s = s;
}
@Override
public void run() {
FileOutputStream fos=null;
try {
//获取输入流对象
InputStream in = s.getInputStream();
//写入文件的流,用来把读取到的数据保存到文件中
//生成一个文件
long time = System.currentTimeMillis();
String filename="itheima"+time+".jpg";
fos=new FileOutputStream("/Users/wangqi/Desktop/upload/"+filename);
//读取客户端发过来的数据
byte[] bs=new byte[1024];
//先读取一次,获取文件名称
int len;
while ((len=in.read(bs))!=-1){
//String str = new String(bs, 0, len);
fos.write(bs,0,len);
}
//获取输出流对象,往客户端回写数据
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 服务端主程序
public class Server {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象,绑定程序的端口号10010
ServerSocket ss=new ServerSocket(10086);
while (true){
//监听客户端
Socket s = ss.accept(); //阻塞,等待客户端过来连接
//开启一个线程,专门为这个客户端提供服务
UploadRunnable ur = new UploadRunnable(s);
Thread t=new Thread(ur);
t.start();
}
}
}