1 TCP
1.1 TCP通信概述
TCP:面向连接的协议(3次握手)
- 客户端---->服务端–>客户端向服务端请求连接
- 客户端<----服务端–>服务端告诉客户端可以连接
- 客户端---->服务端–>客户端直接连接服务端
特殊地址:
- 127.0.0.1–>代表的本机ip 我自己
- localhost
端口号:是每一个应用程序的唯一标识范围0-65535 前1024已经被占用
1.2 实现简单客户端和服务端的交互
编写客户端
客户端
Socket
构造:
Socket(String host, int port)
host:连接服务端的ip地址
自己的计算机做服务器:127.0.0.1(localhost)
port:服务器设置的端口号
步骤:
1.创建Socket对象,指定要连接的服务器ip以及服务器设置的端口号
2.调用Socket中的getOutputStream获取OutputStream,往服务器上发请求(写数据)
3.调用Socket中国的getInputStream,读取服务端响应回来的结果(读数据)
4.关流
/**
* 编写客户端
*/
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
InputStream is = null;
//创建客户端对象
try {
socket = new Socket("127.0.0.1",8888);
//调用Socket中的getOutputStream方法往服务端写请求(写数据)
os = socket.getOutputStream();
os.write("我想要一个看小视频的网站".getBytes());
//调用getInputStream读取服务端响应的结果(读数据)
is = socket.getInputStream();
//创建字节数组
byte[]bytes = new byte[1024];
//因为只读一条数据,不用while循环了
int read = is.read(bytes);
System.out.println("==========服务端响应的结果=========");
System.out.println(new String(bytes,0,read));
} catch (IOException e) {
e.printStackTrace();
}finally {
//关流
try {
if(os != null && is != null && socket != null){
os.close();
is.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
编写服务端
服务端:ServerSocket:
构造:
ServerSocket(int port)
port:是服务器设置的端口号
方法:
Socket accept()-->等待接收连接服务端的客户端对象
那个客户端连接我这个服务端,此
方法返回的Socket对象就是哪个
客户端的Socket对象
步骤:
1.创建ServerSoceket,设置自己的端口号
2.调用accept方法获取连接服务端的客户端对象
3.调用getInputStream用来读取客户端发来的请求数据(读数据)
4.调用getOutputStream往客户端响应一条数据(写数据)
5.关闭资源
public class Server {
public static void main(String[] args) throws Exception{
//创建服务端对象,设置自己的端口号:要和客户端传过来的一致
ServerSocket serverSocket = new ServerSocket(8888);
//调用accept方法获取客户端对象
Socket accept = serverSocket.accept();
//获取客户端传过来的数据
InputStream is = accept.getInputStream();
//读取:
byte[]bytes = new byte[1024];
int read = is.read(bytes);
System.out.println("============这是客户端传过来的数据=============");
System.out.println(new String(bytes,0,read));
//服务端响应
OutputStream os = accept.getOutputStream();
os.write("给你一个小视频:".getBytes());
//关闭资源
os.close();
is.close();
accept.close();
serverSocket.close();
}
}
1.3 文件上传
客户端
客户端:
步骤:
1.创建Socket对象,指定服务端的ip以及端口号
2.创建FileInputStream用于读取硬盘上的图片
3.调用getOutputStream用于往服务端写我们读到的图片
4.边读边写
5.调用getInputStream.接收服务端响应回来的结果
6.关闭资源
/**
* 客户端
*/
public class Client {
public static void main(String[] args) throws Exception{
//创建Socket对象,设置服务端的ip及端口号
Socket socket = new Socket("127.0.0.1", 6666);
//创建FileInputStream读取本地图片
FileInputStream fis = new FileInputStream("D:\\test1\\2.jpg");
//创建socket中的getOutStream往服务器端写读到的图片
OutputStream os = socket.getOutputStream();
//边读边写
byte[]bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
//通知服务器端.当读到-1的时候不写数据了,让服务器端继续往下执行
socket.shutdownOutput();
System.out.println("------------以下是接收服务端响应回来的结果-----------");
//调用getInputStream读取服务端响应的数据
InputStream is = socket.getInputStream();
//遍历
byte[]bytes1 = new byte[1024];
int len1 = is.read(bytes1);
System.out.println(new String(bytes1,0,len1));
//6.关闭资源
is.close();
os.close();
fis.close();
socket.close();
}
}
服务端
服务端:
步骤:
1.创建ServerSocket对象,设置端口号
2.调用accept方法,等待接收连接过来的客户端对象
3.调用getInputStream.读取客户端歇过来的图片
4.创建FileOutputStream对象,往硬盘上的指定位置写图片数据
5.边读边写
6.调用getOputStream往客户端写数据->响应一个"文件上传成功"
7.关闭资源
异常:Address already in use: JVM_Bind:连续来了2次服务器(端口号被占用)
/**
* 服务端
*/
public class Server {
public static void main(String[] args) throws Exception{
//读取客户端传输过来的数据
ServerSocket serverSocket = new ServerSocket(6666);
//多线程
while (true){
new Thread(()->{
Socket accept = null;
InputStream is = null;
FileOutputStream fos = null;
OutputStream os = null;
try{
//和客户端建立连接
accept = serverSocket.accept();
//读取数据
is = accept.getInputStream();
//复制多个图片,防止覆盖
String name = System.currentTimeMillis() + new Random().nextInt(10000) + ".jpg";
//创建FileOutputStream往指定路径复制图片信息
fos = new FileOutputStream("D:\\test\\"+name);
//边读边写
byte[]bytes = new byte[1024];
int len = 0;
while ((len=is.read(bytes))!=-1){
fos.write(bytes,0,len);
}
System.out.println("----------以下是往客户端响应的结果----------");
//调用getOutStream往客户端响应一个结果
os = accept.getOutputStream();
os.write("复制成功".getBytes());
}catch (Exception e){
e.printStackTrace();
}finally {
//关流
try {
if(os != null && fos != null && is != null && accept != null){
os.close();
fos.close();
is.close();
accept.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
2 模拟B\S服务器
模拟网站服务器,使用浏览器访问自己编写的服务端程序,查看网页效果。
案例分析
- 准备页面数据,web文件夹。
- 我们模拟服务器端,ServerSocket类监听端口,使用浏览器访问,查看网页效果
案例实现
public class BS_Server {
public static void main(String[] args) throws Exception{
//创建ServerSocket对象,指定端口号
ServerSocket serverSocket = new ServerSocket(8888);
while (true){
new Thread(() ->{
try{
//获取客户端对象
Socket accept = serverSocket.accept();
//调用getInputStream获取浏览器发过来的请求
InputStream is = accept.getInputStream();
//创建BufferedReader对象
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//读取第一行
String s = br.readLine();
//处理字符串想办法得到day/web/index.html
String[] s1 = s.split(" ");
String s2 = s1[1];
String substring = s2.substring(1);
//创建FileInputStream读取本地的页面
FileInputStream fis = new FileInputStream(substring);
//调用getOutputStream,往客户端响应页面
OutputStream os = accept.getOutputStream();
os.write("HTTP/1.1 200 OK\r\n".getBytes());//响应行
os.write("Content-Type:text/html\r\n".getBytes());//响应头
os.write("\r\n".getBytes());
byte[] bytes = new byte[1024];
int len;
while((len = fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
//关流
os.close();
fis.close();
br.close();
is.close();
accept.close();
}catch (Exception e){
e.printStackTrace();
}
}).start();
}
}
}
然后在浏览器输入http://localhost:8888/day18/web/index.html就会出效果了