目的:网络编程:在两台不同的计算机之间数据传递
服务器端与客户端的数据传输,单向传递,双向传递,终端接收数据传递等。
-
上传与下载:
客户端 1.文本 2.图片 3.音频 4.视频 服务器端、
技术:
知识点:
* 网络编程:在两台不同的计算机之间数据传递
* 1.QQ聊天
* 2.打开网易APP 刷新界面 就有数据
* 3.打开浏览器 网页www.baidu.com
*
* 客户端:手机APP 浏览器 桌面QQ
* 服务器端:存储/处理数据
*
* URL : 统一的资源定位
* http://www.baidu.com/search?code=android&type=1
* http/https: 传输协议 Tcp/IP 具体实现
* www.baidu.com :域名 表示一台网络中的电脑
* (ipv4、ipv6)ip地址 : 唯一标识一台网络中的电脑
* 32位:四个部分每个8个字节
* 192.168.43.117 <-> www.baidu.com
*
* DNS服务器: 域名解析
* 将www.baidu.com类型的域名解析为对应的Ip地址
*
* search 对应的后台程序文件 php java jsp
* ? 表示运行这个程序需要传递的参数
* code=android :code是服务器段指定的字段
* & 如果有多个参数 使用&符号链接
*
* ip地址唯一标识某一台电脑
* 端口号:唯一标识电脑上的某一个进程(程序)80
*
* 数据传输:TCP/IP协议
* TCP : 面向链接的 安全 如打电话
* UTP : 面向不链接的 不安全 快 如古代飞鸽传书
*
* 网络中的数据传输:Socket实现 -> 套接字
* Socket类: 客户端
* ServerSocket服务器端
*
* 读取数据: 服务器端读取 客户端读取
* BufferReader -> InputStreamReader -> socket.getInputStream()
* 从终端读取:
* BufferReader -> InputStreamReader -> System.in
* 输出数据:客户端输出 服务器端输出
* BufferedWriter -> OutputStreamWriter -> socket.getOutputStream
* PrintStream -> socket.getOutputStream
实际编程:
(1).简单的服务器端与客户端数据传输;
定义客户端:
//模拟客户端
class Client{
public static void main(String[] args) throws IOException {
//1.创建用于通信的Socket
//指明和谁通信:IP地址 端口号
Socket socket = new Socket("192.168.43.117",8989);
//接收服务器端的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//向服务器端发送数据
//socket.getOutputStream();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好啊");
//输出完毕
socket.shutdownOutput();
}
}
定义服务器端:
//模拟服务器端
class Server{
public static void main(String[] args) throws IOException {
//1.创建服务器端的serverSocket
ServerSocket ss = new ServerSocket(8989);
//2.获取链接的客户端的socket
Socket clientSocket = ss.accept();
//3.向客户端发送数据
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println("登录成功");
//输出完毕
clientSocket.shutdownOutput();
//4.接收客户端发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
调用时必须先运行服务器端再运行客户端。
(2)手动输入内容 发送
以上代码进行简单更改:
class MyClient{
public static void main(String[] args){
//连接服务器端的Socket
Socket socket = null;
try {
socket = new Socket("192.168.43.117", 8888);
//接收服务器信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
// //从终端输出数据,发送给服务器端
// //获取终端数据
// BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
// //获取向客户端的输出数据的输出流
// PrintStream ps = new PrintStream(socket.getOutputStream());
// String txet = null;
// while ((txet = keyin.readLine()) != null){
// ps.println(txet);
// }
}catch (IOException e){
System.out.println("网络出错 请重新登录");
}finally {
try{
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class MyServer{
public static void main(String[] args){
//创建ServerSocket
try(ServerSocket serverSocket = new ServerSocket(8888)){
//监听客服端的连接
Socket clientSocket = serverSocket.accept();
//从终端接收数据
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//获取向客户端的输出数据的输出流
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
//发送给客户端
ps.println(line);
}
// //接收客户端的数据
// BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// String text = null;
// while ((text = br.readLine()) != null){
// System.out.println(text);
// }
}catch (IOException e){
e.printStackTrace();
}
}
}
(3) * 客户端向服务器端发送图片 post上传
class Client1{
public static void main(String[] args) throws IOException {
//连接服务器 获取socket
Socket socket = new Socket("192.168.43.117", 9999);
//创建服务器端对应的输入流 用于接收服务器端发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服务器端发送文件(图片)
//1.将文件写入内存里面
String path = "C:\\Users\\DELL\\Desktop\\1.png";
FileInputStream fis = new FileInputStream(path);
// //2,将内容输出到服务器端
// PrintStream ps= new PrintStream(socket.getOutputStream());
//
// //3.将文件的内容一点一点地传送给服务器
// byte[] buf = new byte[1024];
// int len = -1;
// while ((len = fis.read(buf)) != -1){
// ps.println(new String(buf,0,len));
// }
//2.创建字节流 outputStream
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] buf = new byte[1024];
int len = -1;
while ((len = fis.read(buf)) != -1){
bos.write(buf,0,len);
}
socket.shutdownOutput();
}
}
class Server1{
public static void main(String[] args) throws IOException {
//创建服务器端的ServerSocket
ServerSocket ss = new ServerSocket(9999);
//监听客户端链接
//当有客户端来连接这个服务器 就可以得到对应的socket
//当没有客户端连接 服务器一直在这里等待
Socket socket = ss.accept();
//创建客户端对应的输出流 用于向这个客户端发送数据
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("连接成功 可以发送数据!");
// //接收客户端传递过来的图片
// BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//
// //文件对应的输出流
// String path = "E:\\JavaStudy\\JavaXuexi\\src\\main\\java\\day12\\2.png";
// PrintStream psFile = new PrintStream(new FileOutputStream(path));
//
// String line = null;
// char[] buf = new char[1024];
// int len = -1;
// while ((len = br.read(buf)) != -1){
// //将字符数组转化为字符串
// line = new String(buf,0,len);
// //将字符串写入到文件
// psFile.println(line);
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String path = "E:\\JavaStudy\\JavaXuexi\\src\\main\\java\\day12\\2.png";
FileOutputStream fos = new FileOutputStream(path);
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
fos.write(buf,0,len);
}
}
}
(4) 服务器端与客户端 对聊
- 客户端好服务器端都可以随意地发送内容
- 从终端输入
- 客户端:
主线程:接收终端输入 将终端输入发送给服务器端
子线程:接收服务器端发过来的数据
服务器端:
主线程:接收终端输入 将1终端输入发送给客户端
子线程:接收客户端发过来的数据
定义Clinet,Server类主线程:
class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.43.117", 8888);
//子线程 处理服务端数据
new Thread(new ClientThread(socket)).start();
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//客户端的输出流对象
PrintStream printStream = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null) {
printStream.println(line);
}
}
}
class Server{
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8888);
//获取客户端的socket
Socket socket = ss.accept();
//创建子线程 处理客户端的输入信息
new ServerThread(socket).start();
//终端输入流对象
BufferedReader keyin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//客户端的输出流对象
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
实现子线程,用于接收服务器端或客户端的数据:
/**
* 创建子线程处理客户端接收服务器端的数据
*/
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket 对象
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
//获取输入
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取
String line = null;
while ((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (socket != null) {
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 创建一个子线程处理服务器端接收客户端的数据
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
//
//
try{
if(br != null){
br.close();
}
if(socket != null){
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
5..如何实现群聊
重点思想:在服务器端维护一个数组(socket)
实现服务器端:
class Server{
//保存每一个来连接的socket对象
public static ArrayList sockets = new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
//不停地等待客户端来连接
while (true){
Socket socket = serverSocket.accept();
//保存每一个客户端socket
sockets.add(socket);
//开启一个线程处理每一个客户端的输出
new ServerThread(socket).start();
}
}
}
实现Server接收每个客户端数据传输:
/**
* 创建一个子线程处理服务器端接收客户端的数据
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line = null;
while ((line = br.readLine()) != null){
//群发消息
//遍历Socket维护的数组
for(Socket s : Server.sockets){
//向socket对应的客户端发送消息
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println(line);
}
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
//
//
try{
if(br != null){
br.close();
}
if(socket != null){
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端实现与对聊的代码一样:
class Client{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("10.129.28.253",6666);
//用一个子线程处理服务器端数据
new Thread(new ClientThread(socket)).start();
//主线程处理终端输入 发送给服务器端
BufferedReader keyin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
/**
* 创建子线程处理客户端接收服务器端的数据
*/
class ClientThread implements Runnable{
private Socket socket;
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
//获取服务器端的输入流对象
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}catch (IOException e){
e.printStackTrace();
}finally {
try{
if(br != null){
br.close();
}
if(socket != null){
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
心得:
今天循环写差不多的代码。头都搞晕了,晚自习时是在没精神啊,但效果真的不错,复习时轻轻松松,因为都有印象。