一. 网络通信
1.1 软件结构
这里我们只需要知道B/S架构与C/S架构即可。下面来举例说明。
1.2 网络通信协议
网络通信协议:就是指计算机在计算机网络中实现通信
所要遵守的规则。常见的两类通信协议:UDP协议
、TCP协议
,
UDP:用户数据报协议(User Datagram Protocol)协议是一种面向无连接的协议,也即在通信中,发送方发送数据时不管接收方是否在线,都可以发送。但是这个协议也有缺点就是会偶而出现丢包的现象导致数据丢失,而且UDP协议对于一次性发送的数据大小要限制在64k的范围内才可以成功发送。比如我们生活中使用的视频聊天和qq软件就是基于这种协议的。
TCP协议:传输控制协议 (Transmission Control Protocol),它不同于UDP协议,是一种面向连接的协议。即要保证发送端与接收端确认可以正常连接后才可以发送数据进行通信。相对于UDP而言更加的安全可靠。这里我们需要注意确认正常连接的原理是基于三次握手的。
总结比较两者:UDP效率高但是不安全,TCP效率低但是安全
1.3网络编程三要素
三要素:网络通信协议(前面已讲解)、IP地址、端口号
,IP地址的作用在于找到对应的计算机,可以理解为是给计算机的一个身份证。而IP地址又分为IPV4和IPV6。
IPV4:IPV4地址由4个字节组成,这里给一个常见的形式例子:192.168.65.100每个数字的范围是0-255,一共可以表示42亿个地址。
IPV6:IPV6地址由16个字节组成,一共128位,每两个字节为一组,分为8组,用16进制数来表示.这里给出一个实例:ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
关于IP地址的更多详细介绍可以参见这篇文章:IPV4 地址耗尽会对互联网产生什么影响?
最后我们来介绍一下端口号:前面我们讲解了网络协议和IP地址,前者保证了计算机之间可以发送数据进行通信,后者保证了可以准确的定位计算机,而端口就是在准确定位计算机的基础上定位到计算机的具体的软件或应用程序上。
二. 基于TCP协议的通信程序
使用TCP协议来实现两端通信的步骤:
1.服务端程序预先启动,等待客户端的连接。
2.客户端主动连接客户端,连接成功才可以通信。服务器端不可以主动连接客户端
3.建立连接后,连接中就包含了一个I/O对象,通过这个I/O字节流对象就可以实现通信
代码实现:
//客户端代码
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws IOException {
//获取客户端套接字对象
Socket socket = new Socket("127.0.0.1",8080);
//获取输出流
OutputStream out = socket.getOutputStream();
out.write("我要请求".getBytes());
//获取输入流
InputStream in = socket.getInputStream();
byte[] b = new byte[1024];
int len = in.read(b);
System.out.println(new String(b,0,len));
socket.close();
}
}
//服务器端代码
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws IOException {
//创建服务端对象
ServerSocket server = new ServerSocket(8080);
//获取Socket套接字对象
Socket socket = server.accept();
//获取输入流读取从客户端发来的数据
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = in.read(bytes);
System.out.println(new String(bytes,0,len));
//向客户端发送数据
OutputStream out = socket.getOutputStream();
out.write("我已经收到了".getBytes());
socket.close();
server.close();
}
}
三.实战——文件上传与B/S实例
文件上传:
//客户端
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws IOException {
//获取客户端套接字对象
Socket socket = new Socket("127.0.0.1",8080);
//获取文件输入流
InputStream in = new FileInputStream("D:\\收集信息\\src\\beijing.jpg");
byte[] bytes = new byte[1024*1024];
int len = 0;
//获取网络输出流
OutputStream out = socket.getOutputStream();
while((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
}
//给输入到缓冲区的字节流文件加上终结
socket.shutdownOutput();
//获取网络输入流
InputStream input = socket.getInputStream();
while((len=input.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
in.close();
socket.close();
}
}
//服务器端
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws IOException {
FileOutputStream output = new FileOutputStream("D:\\收集信息\\src\\beijing_new.jpg");
//创建服务端对象
ServerSocket server = new ServerSocket(8080);
//获取Socket套接字对象
Socket socket = server.accept();
//获取输入流读取从客户端发来的数据
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024*1024];
int len = 0;
System.out.println(1234);
while((len = in.read(bytes))!=-1){
output.write(bytes,0,len);
}
System.out.println(1234);
//向客户端发送数据
OutputStream out = socket.getOutputStream();
out.write("我已经收到了".getBytes());
output.close();
socket.close();
server.close();
}
}
B/S加载页面:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
@SuppressWarnings("all")
public class TCPServer{
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
while(true)
{
new Thread(new Runnable() {
@Override
public void run() {
try {
//获取socket
Socket socket = server.accept();
System.out.println("jack");
//获取网络输入流
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
//获取请求行
String line = reader.readLine();
String[] arr = line.split(" ");
String path = arr[1].substring(1);
System.out.println(path);
//获取输出流
OutputStream output = socket.getOutputStream();
FileInputStream in = new FileInputStream(path);
byte[] bytes = new byte[1024];
int len = 0;
// 写入HTTP协议响应头,固定写法
output.write("HTTP/1.1 200 OK\r\n".getBytes());
output.write("Content-Type:text/html\r\n".getBytes());
// 必须要写入空行,否则浏览器不解析
output.write("\r\n".getBytes());
while ((len = in.read(bytes)) != -1) {
output.write(bytes, 0, len);
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
//server.close();
}
}
项目目录结构如下: