需求:完成网络登录功能:
用户输入用户名密码,服务器给出登录成功或失败的提示
TCP编程基于 请求—响应
在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序
第一次通讯中等待连接的程序被称作服务器端(Server)程序
利用IO流实现数据的传输
单向 :只有请求
双向:请求—响应
循环双向:持续(请求—响应)
客户端Socket
此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。 客户端的步骤
1:创建客户端的套接字
2:获取输出流
3:输出流写数据
4:关闭套接字
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//1:创建客户端的套接字 做连接 指定服务器的ip+端口
Socket s = new Socket("192.168.3.135", 10086);
//2:获取输出流
OutputStream os = s.getOutputStream();
//3:写数据
os.write(97);
os.write(98);
os.write(99);
//4:关闭套接字
s.close();
}
}
服务器端ServerSocket
此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
服务器的步骤
1:创建服务器的套接字
2:监听客户端的套接字
3:获取输入流读取内容
4:关闭套接字
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//1:创建服务器的套接字
ServerSocket ss = new ServerSocket(10086);
//2:监听客户端的套接字,并且返回客户端的套接字
Socket s = ss.accept(); //阻塞式方法
//3:获取输入流
InputStream is = s.getInputStream();
//4:读取数据
byte[] by = new byte[1024];
int num = 0;
while((num = is.read())!=-1){
System.out.print((char)num);
}
//5:关闭套接字
s.close();
}
}
优化后
客户端通过键盘录入用户名和密码,发送给服务器
- 注意:一次请求对应一次响应
- 如果多次请求,必须重新建立连接,建立新的scoket
Client
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//1:创建客户端的套接字
Socket s = new Socket("localhost", 10086);
//2:获取输出流
//第1层:字符缓冲输出流
//第2层:字符转换输出流
//第3层:字节输出流
BufferedWriter bw = new BufferedWriter(new
OutputStreamWriter(s.getOutputStream()));
//3 获取输入流
BufferedReader br = new BufferedReader(new
InputStreamReader(s.getInputStream()));
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String userName = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
//3:写数据
bw.write(userName);
bw.newLine();
bw.write(password);
bw.flush();
//bw.close(); //切记,缓冲流写数据,需要刷空!!!
//告诉服务器。客户端这边数据写入完毕
s.shutdownOutput();
//4:读取从服务器响应的数据
String info = br.readLine(); //阻塞式方式
System.out.println(info);
//4:关闭套接字
s.close();
}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class ServerDemo {
public static Map<String, String> getUserInfo() throws
FileNotFoundException, IOException{
Properties p = new Properties();
p.load(new FileInputStream("user.properties"));
String userName = p.getProperty("userName");
String password = p.getProperty("password");
Map<String, String> map = new HashMap<>();
map.put("userName", userName);
map.put("password", password);
return map;
}
public static void main(String[] args) throws IOException {
//1:创建服务器端套接字
ServerSocket ss = new ServerSocket(10086);
//2:监听客户端的套接字
Socket s = ss.accept();
//3:获取输入流
//第1层:字符缓冲输入流
//第2层:字符转换输入流
//第3层:字节输入流
BufferedReader br = new BufferedReader(new
InputStreamReader(s.getInputStream()));
//4:获取输出流
BufferedWriter bw = new BufferedWriter(new
OutputStreamWriter(s.getOutputStream()));
//4:读取数据
String userName = br.readLine();
String password = br.readLine();
//5:判断用户名和密码
//获取正确的用户名和密码
Map<String, String> map = getUserInfo();
System.out.println(userName);
System.out.println("--------------------------");
if(map.get("userName").equals(userName)&&map.get("password"
).equals(password)){
//需要将响应返回给客户端
//System.out.println("登陆成功");
bw.write("登陆成功");
bw.flush();
}else{
bw.write("登陆失败");
bw.flush();
}
//5:关闭客户端套接字
s.close();
}
}
upload
需求:客户端上传文件给服务器
源地址:D://工具//
目的地:当前项目
客户端步骤
1:创建一个输入流读取D://工具/某一个文件,读取到程序中
2:创建客户端的套接字
3:通过客户端的套接字获取输出流
4:将程序中的文件通过输出流写入到服务器
5:关闭套接字
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Client {
/**
* 遍历需要上传的文件
*/
public static String dirFile(){
Scanner sc = new Scanner(System.in);
//创建Map集合保存文件的编号以及文件的路径
Map<String, String> map = new HashMap<>();
System.out.println("---客户端上传文件---");
System.out.println("请选择要上传的文件编号:");
//1:创建一个File文件
File file = new File("D:/工具");
//2:遍历File的目录
File[] listFiles = file.listFiles();
int count = 1;
for (File file2 : listFiles) {
if(file2.isFile()){
System.out.println((count)+":"+file2.getAbsolutePath());
//保存编号和文件名
map.put(String.valueOf(count), file2.getAbsolutePath());
count++;
}
}
//录入文件的编号
String num = sc.nextLine();
//通过录入的编号取集合中找文件的路径
String path = map.get(num);
//返回文件路径
return path;
}
public static void upload() throws IOException{
//1:获取文件的路径
String path = dirFile();
//2:创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(path));
//3:创建客户端的套接字
Socket s = new Socket("127.0.0.1", 10086);
//4:通过套接字获取输出流
BufferedOutputStream bos = new BufferedOutputStream
(s.getOutputStream());
//5:一边读取,一边写入
byte [] by = new byte[1024];
int num = 0;
while((num=bis.read(by))!=-1){
//把文件写入服务器
bos.write(by, 0, num);
}
//通知服务器客户端写入完毕
s.shutdownOutput();
//获取一个输入流
BufferedReader br = new BufferedReader(new
InputStreamReader(s.getInputStream()));
String info = br.readLine();
System.out.println(info);
//6:关闭流和套接字
bis.close();
s.close();
}
public static void main(String[] args) {
try {
upload();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
public class Server {
/*
* 服务器接受客户端上传的文件
* 保存地址:当先项目下的file文件下
*
*/
public static void main(String[] args) throws IOException {
//1创建服务器端的套接字
ServerSocket ss = new ServerSocket(10086);
System.out.println("等待文件上传...");
//2:监听客户端的套接字,并且获取套接字
Socket s = ss.accept();
//3:通过客户端的套接字获取一个输入流
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
//4:创建一个输出流
UUID uuid = UUID.randomUUID();
System.out.println(uuid);
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("file//"+uuid.toString()+".zip"));
//4:读取流中内容
byte[] by = new byte[1024];
int num = 0;
while((num=bis.read(by))!=-1){
bos.write(by, 0, num);
}
System.out.println("---------------");
//给客户端一个响应 :上传成功
//获取一个输出流
BufferedWriter bw = new BufferedWriter(new
OutputStreamWriter(s.getOutputStream())) ;
bw.write("上传成功");
bw.flush();
//5:关闭流
//bos.close();
s.close();
}
}