Java网络编程
一,网络编程入门
1.1 软件结构
c/s结构:全称是client/serve结构,是指的客户端和服务端的结构,常见的有QQ,迅雷。
B/S:全称是brower/server结构,是指的浏览器和服务端的结构,常见的就是网页。
1.2网络通信协议
网络通信协议:通过计算机网络可以使多台计算机实现连接,位于同一个网络的计算机在网络连接和通信时需要遵守一定的规则。者就好比在道路上行走需要遵守交通规则一样。在计算机网络中,这些链接和通信的规则被称为网络通信协议,他对数据传输的格式,速度,传输步骤都做了统一的规定,通信双方必须要在这样的规则下面完成数据交换
TCP/IP协议:传输控制协议/因特网互联协议。是互联网最基本最广泛的协议。采用了四层的分层模型,每一层都呼叫他的下一层提供的协议来完成自己的需求。
四层:
-
物理层(数据链路层)
-
网络层
-
传输层 TCP UDP
-
应用层 HTTP FTP TFTP SMTP SNMP DNS
1.3网络通信协议的分类
UDP(User Datagram Protocol)
用户数据报协议,是无连接协议,即在数据传输时数据的发送端和接收端不存在逻辑连接,简单地说当一台计算机向另一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时也不会反馈是否接收到数据。
特点:消耗资源少,一般用来用于音频视频,偶尔丢包。传输重要数据的时候可能会出现丢包。数据被限制在64kb之内超过了这个范围便不可传输
TCP(Transimission Control Protocol)
传输控制协议,是面向连接的通信协议,即传输之前发送端和接收端需要先建立逻辑连接,然后在传输数据。他提供了两台计算机之间可靠无差错的数据传输。在TCP连接之前必须要明确客户端和服务端之间,由客户端向服务器发出请求,每次连接的创建都需要经历三次握手。
用途很广泛:文件的下载文件的上传,网页的浏览
1.4 网络编程三要素
-
协议
-
IP地址
互联网协议地址:是一个32个二进制数组成的被分成四个字节表示成abcd的形式,IPv6则是128个二进制数字通产被分成16个字节
127.0.0.1是自己本机的IP地址localhost也代表本地的地址
-
端口号
端口号由16个字节表示,1024之前的端口号不可以被使用已经分配给了已知的网络软件
常用的端口号
- 网络的端口:80
- mysql:3306 oracle:1521
- Tomcat:8080
二,TCP通信程序
2.1概述
TCP通信严格区分客户端和服务端,两端都是计算机。服务端的配置比较高。
服务器端先启动,服务器不会主动请求客户端,必须使用客户端请求服务器端,客户端和服务器端建立一个逻辑连接,而这个连接包含一个IO对象,服务器端和客户端使用IO 流进行通信,通信的不仅是字符因此对象是字节流对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vs0n9HXd-1581428644383)(C:\Users\caixiaocai\Desktop\leetcode\网络编程.PNG)]
-
多个客户端可以和同一个服务器连接,服务器必须要明确和哪一个客户端交互,在服务器端就有一个方法accept。可以获取到请求的客户端对象
-
多个客户端同时和服务器交互,就需要多个IO流对象。但是服务器是没有IO流的,服务器获取请求的客户端对象socket 使用每个客户端socket中提供的IO流和客户端进行交互
服务器使用客户端的字节输入流读取客户端发送的数据
服务器使用客户端的字节输出流给客户端回写数据
简单来说:服务器使用客户端的流和客户端进行交互
2.2 Socket
套接字:包含了IP地址和端口的网络单位
注意:
- 客户端和服务器之间进行交互,必须使用Socket提供的网络流不能使用自己创建的流对象
- 当客户端创建套接字后,就会请求服务器和服务器经过三次握手进行连接,这时候如果服务器没有启动就会发出异常,如果这时候服务器已经启动就建立连接
客户端Socket构造方法
Socket(String host,int post);//服务器主机名称或者Ip地址
//两个方法
getOutputStream();
getInputStream();
close();
客户端代码
package tcp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClient {
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
Socket sc = new Socket("127.0.0.1",8080);
OutputStream os =sc.getOutputStream();
os.write("你好服务器".getBytes());
InputStream is =sc.getInputStream();
byte[] bytes=new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
sc.close();
}
}
服务端
ServerSocket(port)
服务端代码
package tcp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("服务器程序开始");
ServerSocket server = new ServerSocket(8080);
Socket sc =server.accept();
InputStream is = sc.getInputStream();
byte[] bytes=new byte[1024];
int len=is.read(bytes);
System.out.println(new String(bytes,0,len));
OutputStream os =sc.getOutputStream();
os.write("收到谢谢".getBytes());
sc.close();
server.close();
System.out.println("服务器程序结束");
}
}
三,综合案例
3.1文件上传案例
本地的文件上传到服务器上面,先开启服务器端然后再打开客服端发送请求
客户端:利用本地读取到的数据上传到服务器
package fileUpload;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
Socket socket = new Socket("127.0.0.1",8886);
FileInputStream fis = new FileInputStream("C:\\Users\\caixiaocai\\Desktop\\name\\in.txt");
OutputStream os = socket.getOutputStream();
byte[] bytes = new byte[1024];
int len =0;
while((len=fis.read(bytes))!=-1) {
os.write(bytes,0,len);
}
socket.close();
}
}
服务端:接受了来自客户端的数据并且保存在服务器本地磁盘中,利用多线程来提高了速度
package fileUpload;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub\S
//优化一下,如果文件夹不存在就重新建立一个,如果存在的话就保存在文件夹里面
File file = new File("C:\\Users\\caixiaocai\\Desktop\\name\\a");
if (!file.exists()) {
file.mkdirs();
}
ServerSocket serversocket = new ServerSocket(8886);
while (true) {//可以多次的上传数据
Socket socket = serversocket.accept();
//创建多线程来完成任务
new Thread(new Runnable() {
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
long value = System.currentTimeMillis();//这里作为文件名来避免覆盖掉重复的文件
FileOutputStream fis = new FileOutputStream(file+"\\"+value+"server.txt");
int len = 0;
byte[] bytes = new byte[1024];
while((len=is.read(bytes))!=-1) {
fis.write(bytes,0,len);
}
System.out.println("上传结束");
fis.close();
}catch(IOException e) {
System.out.println(e);
}
}
}).start();
}
}
}
3.2 模拟B/S服务器(扩展知识点)
package name;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serversocket = new ServerSocket(8888);
while (true) {
Socket socket = serversocket.accept();
new Thread(new Runnable() {//开启多线程
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = br.readLine();
String[] arr = line.split(" ");
String htmlpath = arr[1].substring(1);//获取网页请求的地址
FileInputStream fis = new FileInputStream(htmlpath);
OutputStream os = socket.getOutputStream();
//下面三行是http内容
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content-Type:text/html\r\n".getBytes());
os.write("\r\n".getBytes());
int len=0;
byte[] bytes = new byte[1024];
while((len=fis.read(bytes))!=-1) {
os.write(bytes,0,len);
}
fis.close();
System.out.println("程序结束");
}catch(IOException e) {
System.out.println(e);
}
}
}).start();
}
}
}
t len=0;
byte[] bytes = new byte[1024];
while((len=fis.read(bytes))!=-1) {
os.write(bytes,0,len);
}
fis.close();
System.out.println(“程序结束”);
}catch(IOException e) {
System.out.println(e);
}
}
}).start();
}
}
}