目录
基本概念
网络编程TCP
Socket类
ServerSocket类
TCP网络编程的原理
?案例:文件上传
基本概念
软件结构
- C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。
- B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。
网络通信协议:TCP/IP协议
? ? ? ? 它的传输层包含TCP、UDP
TCP协议:TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。(三次握手)
UDP协议:UDP协议是一个面向无连接的协议。传输数据时,不需要建立连接,不管对方端服务是否启动,直接将数据、数据源和目的地都封装在数据包中,直接发送。(传输速度快、容易丢包)
网络编程三要素
协议
IP地址:IP地址用来给一个网络中的计算机设备做唯一的编号。(通过ip可以找到这台计算机)
端口号:可以唯一标识设备中的进程(应用程序)。(通过端口号可以找到这台计算机上指定的应用程序)
网络编程TCP
Socket类
构造方法????????
- public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null ,则相当于指定地址为回送地址。
成员方法
- public InputStream getInputStream() : 返回此套接字的输入流。(获取传回的数据)
- public OutputStream getOutputStream() : 返回此套接字的输出流。(发送数据)
- public void close() :关闭此套接字。
- public void shutdownOutput() : 禁用此套接字的输出流。(传入结束标志)
ServerSocket类
构造方法
public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。
成员方法
public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。
TCP网络编程的原理
服务器如何确定具体的客户端:通过accept()获取到请求的客户端对象
服务器是没有IO流的,都是使用客户端自己的IO流与客户端进行交互
步骤:
- 客户端使用网络字节输出流向服务器发送数据
- 服务器使用网络字节输入流查看客户端发送的数据
- 服务器使用网络字节输出流向客户端回传数据
- 客户端使用网络字节输入流查看服务器的回传数据
示例代码:tcp简单的通信
//客户端
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 6666);
OutputStream outputStream = socket.getOutputStream();//获取输出流 发送数据
outputStream.write("客户端传来的数据".getBytes());
InputStream inputStream = socket.getInputStream();//获取输入流 获取回传数据
byte[]bytes=new byte[1024];
int len;
while ((len=inputStream.read(bytes))!=-1){//因为结束标记没有进入while循环,所以需要添加结束标记;不然客户端会一直接收(死循环)
System.out.println(new String(bytes,0,len));
}
socket.shutdownOutput();//添加结束标记
outputStream.close();
inputStream.close();
socket.close();
}
//服务器
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6666);
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();//获取输入流 获取回传数据
byte[]bytes=new byte[1024];
int len=inputStream.read(bytes);
System.out.println(new String(bytes,0,len))
OutputStream outputStream = socket.getOutputStream();
outputStream.write("服务器传回的数据".getBytes());
inputStream.close();
outputStream.close();
socket.close();
}
?案例:文件上传
步骤:
- 客户端本地输入流:读取文件
- 客户端网络输出流:将读取的文件发送
- 服务器网络输入流:读取收到的文件
- 服务器本地输出流:将文件保存到服务器的磁盘中
- 服务器网络输出流:回传数据
- 客户端网络输入流:接收回传数据
?注:服务器中获取一个请求Socket对象,就会创建一个线程(可以提高性能)
//服务器
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(1000);
while (true){
new Thread(()->{//创建线程 并且开启线程
try {
Socket socket1 = socket.accept();
File file = new File("D:\\mountserada");
if(!file.exists()){file.mkdirs();}
//本地输出流
FileOutputStream fileOutputStream = new FileOutputStream(file.getAbsolutePath()+"\\" + System.currentTimeMillis() + ".txt");
//读取收到的文件
InputStream inputStream = socket1.getInputStream();
byte[]bytes=new byte[1024];
int len;
while ((len=inputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,len);
}
//回传数据
OutputStream outputStream = socket1.getOutputStream();
outputStream.write("上传完成!!!".getBytes());
fileOutputStream.close();
outputStream.close();
inputStream.close();
socket1.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
//客户端
public static void main(String[] args) throws IOException {
//读取文件
FileInputStream inputStream = new FileInputStream("test1.txt");
Socket socket = new Socket("localhost", 1000);
//发送文件
OutputStream outputStream = socket.getOutputStream();
byte[]bytes=new byte[1024];
int len;
while ((len=inputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
socket.shutdownOutput();
//读回传
InputStream inputStream1 = socket.getInputStream();
while ((len=inputStream1.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
inputStream.close();
inputStream1.close();
outputStream.close();
socket.close();
}
|