day40-网络编程02

打印 上一主题 下一主题

主题 878|帖子 878|积分 2634

Java网络编程02

4.TCP网络通信编程


  • 基本介绍

    • 基于客户端--服务端的网络通信
    • 底层使用的是TCP/IP协议
    • 应用场景举例:客户端发送数据,服务端接收并显示控制台
    • 基于Scoket的TCP编程

4.1应用案例1:(使用字节流)


  • 编写一个服务器端,和一个客户端
  • 服务器端在9999端口监听
  • 客户端连接到服务器端,发送“hello,server”,然后退出
  • 服务器端接收到客户端发送的信息,输出,并结束

客户端思路:
1.连接服务端(ip,端口)
2.连接上后,生成socket,通过socket.getOutputStream()
3.通过输出流,写入数据到数据通道
  1. package li.network.socket;
  2. import java.io.IOException;
  3. import java.io.OutputStream;
  4. import java.net.InetAddress;
  5. import java.net.Socket;
  6. //发送"hello,server"给服务端
  7. public class SocketTCP01Client {
  8.     public static void main(String[] args) throws IOException {
  9.         //1.连接服务端(ip,端口)
  10.         Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//连接服务端的主机的端口,在这里是本机
  11.         System.out.println("客户端 socket返回=" + socket.getClass());
  12.         //2.连接上后,生成socket,通过socket.getOutputStream()
  13.         //  得到和 socket 对象关联的输出流对象
  14.         OutputStream outputStream = socket.getOutputStream();
  15.         //3.通过输出流,写入数据到数据通道
  16.         outputStream.write("hello,server".getBytes());
  17.         //4. 关闭流对象和socket(必须关闭)
  18.         outputStream.close();
  19.         socket.close();
  20.         System.out.println("客户端退出");
  21.     }
  22. }
复制代码
服务器端思路:
1.在本机的9999端口监听,等待连接
2.当没有客户端连接9999端口时,程序将会阻塞,等待连接
3.通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
  1. package li.network.socket;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. public class SocketTCP01Server {
  7.     public static void main(String[] args) throws IOException {
  8.         // 1.在本机的9999端口监听,等待连接
  9.         // 要求在本机没有其他服务在监听9999
  10.         // ServerSocket 可以通过 accept() 方法返回多个 Socket[多个客户端连接服务器的并发]
  11.         ServerSocket serverSocket = new ServerSocket(9999);
  12.         System.out.println("服务端在9999端口监听,等待连接...");
  13.         // 2.当没有客户端连接9999端口时,程序会阻塞,等待连接
  14.         // 如果有客户端连接则会返回一个socket对象,程序继续
  15.         Socket socket = serverSocket.accept();
  16.         System.out.println("服务器端 socket=" + socket.getClass());
  17.         // 3.通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
  18.         InputStream inputStream = socket.getInputStream();
  19.         // 4.IO读取
  20.         byte[] buf = new byte[1024];
  21.         int readLen = 0;
  22.         while ((readLen = inputStream.read(buf)) != -1) {
  23.             System.out.println(new String(buf, 0, readLen));//根据实际读取到的长度显示内容
  24.         }
  25.         // 5. 关闭流对象和socket(必须关闭)
  26.         inputStream.close();
  27.         socket.close();
  28.         serverSocket.close();//关闭serverSocket
  29.     }
  30. }
复制代码

  • 要先运行服务端,这里显示正在等待连接客户端:

  • 再运行客户端程序,得到一个socket,通过输出流将数据写入到数通道里面,然后退出:

  • 服务器端会通过输入流不停地读取,把数据输出到控制台上,然后关闭退出:
4.2应用案例2:(使用字节流)


  • 编写一个服务器端,和一个客户端
  • 服务器端在9999端口监听
  • 客户端连接到服务器端,发送“hello,server”,并接收服务器端回发的“hello,client”,再退出
  • 服务器端接收到客户端发送的信息然后输出,并发送“hello,client”,再退出
注意设置写入结束标记socket.shutdownOutput();   否则程序会认为还在写入数据。
服务端Server:
  1. package li.network.socket;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. @SuppressWarnings("all")
  8. public class SocketTCP02Server {
  9.     public static void main(String[] args) throws IOException {
  10.         // 1.在本机的9999端口监听,等待连接
  11.         // 要求在本机没有其他服务在监听9999
  12.         // ServerSocket 可以通过 accept() 方法返回多个 Socket[多个客户端连接服务器的并发]
  13.         ServerSocket serverSocket = new ServerSocket(9999);
  14.         System.out.println("服务端在9999端口监听,等待连接...");
  15.         // 2.当没有客户端连接9999端口时,程序会阻塞,等待连接
  16.         // 如果有客户端连接则会返回一个socket对象,程序继续
  17.         Socket socket = serverSocket.accept();
  18.         System.out.println("服务器端 socket=" + socket.getClass());
  19.         // 3.获取数据,通过socket.getInputStream()读取客户端写入数据通道的数据,并显示
  20.         InputStream inputStream = socket.getInputStream();
  21.         //IO读取
  22.         byte[] buf = new byte[1024];
  23.         int readLen = 0;
  24.         while ((readLen = inputStream.read(buf)) != -1) {
  25.             System.out.println(new String(buf, 0, readLen));//根据实际读取到的字符串长度显示内容
  26.         }
  27.         // 4. 回话,写入数据
  28.         // 获取socket相关的输出流
  29.         OutputStream outputStream = socket.getOutputStream();
  30.         outputStream.write("hello,client".getBytes());
  31.         //设置写入结束标记
  32.         socket.shutdownOutput();
  33.         // 5. 关闭流对象和socket(必须关闭)
  34.         inputStream.close();
  35.         outputStream.close();
  36.         socket.close();
  37.         serverSocket.close();//关闭serverSocket
  38.     }
  39. }
复制代码
客户端Client:
  1. package li.network.socket;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.net.InetAddress;
  6. import java.net.Socket;
  7. @SuppressWarnings("all")
  8. //发送"hello,server"给服务端
  9. public class SocketTCP02Client {
  10.     public static void main(String[] args) throws IOException {
  11.         //1.连接服务端(ip,端口)
  12.         Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//连接服务端的主机的端口,在这里是本机
  13.         System.out.println("客户端 socket返回=" + socket.getClass());
  14.         //2.连接上后,生成socket,通过socket.getOutputStream()
  15.         //  得到和 socket 对象关联的输出流对象
  16.         OutputStream outputStream = socket.getOutputStream();
  17.         //3.通过输出流,写入数据到数据通道
  18.         outputStream.write("hello,server".getBytes());
  19.         //设置写入结束标记
  20.         socket.shutdownOutput();
  21.         //4. 获取数据
  22.         // 获取和socket相关联的输入流,并显示
  23.         InputStream inputStream = socket.getInputStream();
  24.         byte[] buf = new byte[1024];
  25.         int readLen = 0;
  26.         while ((readLen = inputStream.read(buf)) != -1) {
  27.             System.out.println(new String(buf, 0, readLen));
  28.         }
  29.         //5. 关闭流对象和socket(必须关闭)
  30.         outputStream.close();
  31.         inputStream.close();
  32.         socket.close();
  33.         System.out.println("客户端退出");
  34.     }
  35. }
复制代码

  • 服务端等待客户端连接:

  • 客户端往数据通道写入数据“hello,server,并接受到服务端发送的数据“hello,client”

  • 服务端接收到数据:
4.3应用案例3:(使用字符流)


  • 编写一个服务端,一个客户端
  • 服务端在9999端口监听
  • 客户端连接到服务端,发送“hello,server”,并接收到服务端会发的“hello,client”,然后退出
  • 服务端接收到 客户端发送的信息,输出,并发送“hello,client”,再退出
思路答题与应用案例2一致,这里要求使用字符流,那么在拿到输入/输出字符流之后,使用转换流,将其转换为字符流即可。
PS:设置写入结束标记:除了使用socket.shutdownOutput();  还可以使用writer.newLine(),如果使用这种结束标志的话,需要使用readLine()的方式读取
注意点:如果使用的是字符流,需要我们手动刷新xx.flush();,否则数据不会写入数据通道
服务端Server:
  1. package li.network.socket;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. //使用字符流
  6. @SuppressWarnings("all")
  7. public class SocketTCP03Server {
  8.     public static void main(String[] args) throws IOException {
  9.         // 1.在本机的9999端口监听,等待连接
  10.         // 要求在本机没有其他服务在监听9999
  11.         // ServerSocket 可以通过 accept() 方法返回多个 Socket[多个客户端连接服务器的并发]
  12.         ServerSocket serverSocket = new ServerSocket(9999);
  13.         System.out.println("服务端在9999端口监听,等待连接...");
  14.         // 2.当没有客户端连接9999端口时,程序会阻塞,等待连接
  15.         // 如果有客户端连接则会返回一个socket对象,程序继续
  16.         Socket socket = serverSocket.accept();
  17.         System.out.println("服务器端 socket=" + socket.getClass());
  18.         // 3.获取数据,通过socket.getInputStream()读取客户端写入数据通道的数据,并显示
  19.         InputStream inputStream = socket.getInputStream();
  20.         //IO读取---使用字符流
  21.         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
  22.         String s = bufferedReader.readLine();
  23.         System.out.println(s);//输出
  24.         // 4. 回话,写入数据
  25.         // 获取socket相关的输出流
  26.         OutputStream outputStream = socket.getOutputStream();
  27.         BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
  28.         bufferedWriter.write("hello,client 字符流");
  29.         bufferedWriter.newLine();//插入一个换行符,表示回复内容的结束
  30.         bufferedWriter.flush();//手动刷新
  31.         // 5. 关闭流对象和socket(必须关闭)
  32.         bufferedWriter.close();//关闭外层流
  33.         bufferedReader.close();
  34.         socket.close();
  35.         serverSocket.close();//关闭serverSocket
  36.     }
  37. }
复制代码
客户端Client:
  1. package li.network.socket;
  2. import java.io.*;
  3. import java.net.InetAddress;
  4. import java.net.Socket;
  5. @SuppressWarnings("all")
  6. //发送"hello,server"给服务端,使用字符流
  7. public class SocketTCP03Client {
  8.     public static void main(String[] args) throws IOException {
  9.         //1.连接服务端(ip,端口)
  10.         Socket socket = new Socket(InetAddress.getLocalHost(), 9999);//连接服务端的主机的端口,在这里是本机
  11.         System.out.println("客户端 socket返回=" + socket.getClass());
  12.         //2.连接上后,生成socket,通过socket.getOutputStream()
  13.         //  得到和 socket 对象关联的输出流对象
  14.         OutputStream outputStream = socket.getOutputStream();
  15.         //3.通过输出流,写入数据到数据通道----使用字符流
  16.         BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
  17.         bufferedWriter.write("hello,server 字符流");
  18.         bufferedWriter.newLine();//插入一个换行符,表示写入的内容结束,注意:要求对方使用readLine()!!!!
  19.         //如果使用的是字符流,需要我们手动刷新,否则数据不会写入数据通道
  20.         bufferedWriter.flush();
  21.         //4. 获取数据
  22.         // 获取和socket相关联的输入流,并显示
  23.         InputStream inputStream = socket.getInputStream();
  24.         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
  25.         String s = bufferedReader.readLine();
  26.         System.out.println(s);
  27.         //5. 关闭流对象和socket(必须关闭)
  28.         bufferedReader.close();//关闭外层流
  29.         bufferedWriter.close();
  30.         socket.close();
  31.         System.out.println("客户端退出");
  32.     }
  33. }
复制代码
4.4应用案例4:


  • 编写一个服务端和一个客户端
  • 服务器端在端口8888监听
  • 客户端连接到服务端,并发送一张图片
  • 服务器端接收到客户端发送的图片,保存到src目录下,然后发送“收到图片”,再退出
  • 客户端接收到服务端的回话:“收到图片“ 之后,再退出
  • 该程序要求使用StreamUtils.java
说明:使用BufferedInputStreasm和BufferedOutputStream字节流
思路如下:

  • 客户端这边先将数据传输到客户端程序中,然后通过socket获取数据通道,将文件数据发送给服务端;
  • 服务端这边,先是得到数据通道上的数据(传输到服务端程序中),然后使用将程序中的文件数据输出到某个目录下,之后在将“收到图片”的消息输出到数据通道上
  • 客户端通过socket,从数据通道上获取回复消息,并打印在控制台上
工具类StreamUtils:
  1. package li.network.upload;
  2. import java.io.BufferedReader;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.InputStreamReader;
  7. /**
  8. * 此类用于演示关于流的读写方法
  9. *
  10. */
  11. public class StreamUtils {
  12.    /**
  13.     * 功能:将输入流转换成byte[],即可以把文件的内容写入到byte[]
  14.     * @param is
  15.     * @return
  16.     * @throws Exception
  17.     */
  18.    public static byte[] streamToByteArray(InputStream is) throws Exception{
  19.       ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
  20.       byte[] b = new byte[1024];//字节数组
  21.       int len;
  22.       while((len=is.read(b))!=-1){//循环读取
  23.          bos.write(b, 0, len);//把读取到的数据写入到 bos流中
  24.       }
  25.       byte[] array = bos.toByteArray();//然后将bos 转成为一个字节数组
  26.       bos.close();
  27.       return array;
  28.    }
  29.    /**
  30.     * 功能:将InputStream转换成String
  31.     * @param is
  32.     * @return
  33.     * @throws Exception
  34.     */
  35.    
  36.    public static String streamToString(InputStream is) throws Exception{
  37.       BufferedReader reader = new BufferedReader(new InputStreamReader(is));
  38.       StringBuilder builder= new StringBuilder();
  39.       String line;
  40.       while((line=reader.readLine())!=null){ //当读取到 null时,就表示结束
  41.          builder.append(line+"\r\n");
  42.       }
  43.       return builder.toString();
  44.       
  45.    }
  46. }
复制代码
服务端Server:
  1. package li.network.upload;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. //文件上传的服务端
  6. public class TCPFileUploadServer {
  7.     public static void main(String[] args) throws Exception {
  8.         // 1.服务端在监听8888端口(这里是在本机进行)
  9.         ServerSocket serverSocket = new ServerSocket(8888);
  10.         System.out.println("服务端在8888端口监听...");
  11.         // 2.等待连接
  12.         Socket socket = serverSocket.accept();
  13.         //3.读取数据通道的数据
  14.         //通过socket获得输入流
  15.         //创建对象
  16.         BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
  17.         //写入到程序中
  18.         byte[] bytes = StreamUtils.streamToByteArray(bis);//streamToByteArray方法:将输入流转换成byte[]
  19.         //4.将得到的bytes数组(文件数据)写入到指定的路径,就得到一个文件
  20.         String destFilePath = "src\\copy.png";
  21.         //创建对象
  22.         BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
  23.         //写入数据到目录中
  24.         bos.write(bytes);
  25.         bos.close();
  26.         //5.收到图片后,向客户端回复“收到图片”
  27.         //通过socket获得输出流
  28.         //创建对象
  29.         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  30.         bw.write("收到图片");
  31.         bw.flush();//把内容刷新到数据通道
  32.         socket.shutdownOutput();//设置写入结束标记
  33.         //6.关闭其他资源
  34.         bw.close();
  35.         bis.close();
  36.         socket.close();
  37.         serverSocket.close();
  38.     }
  39. }
复制代码
客户端Client:
  1. package li.network.upload;
  2. import java.io.BufferedInputStream;
  3. import java.io.BufferedOutputStream;
  4. import java.io.FileInputStream;
  5. import java.io.InputStream;
  6. import java.net.InetAddress;
  7. import java.net.Socket;
  8. //文件上传的客户端
  9. public class TCPFileUploadClient {
  10.     public static void main(String[] args) throws Exception {
  11.         //1.客户端连接服务端,得到一个socket对象
  12.         Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
  13.         //2.创建读取磁盘文件的输入流
  14.         String filePath = "d:\\ggmm.jpg";
  15.         //创建对象
  16.         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
  17.         //这里的 bytes 就是 文件filePath 对应的字节数组
  18.         //读取数据到程序中
  19.         byte[] bytes = StreamUtils.streamToByteArray(bis);
  20.         //3.通过socket获取输出流,将bytes数据发送到服务端
  21.         //创建对象
  22.         BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
  23.         //写入数据通道
  24.         bos.write(bytes);//将文件对应的字节数组写入到数据通道
  25.         bis.close();
  26.         socket.shutdownOutput();//设置写入数据的结束标志
  27.         //4.获取服务端回复的消息
  28.         InputStream inputStream = socket.getInputStream();
  29.         String s = StreamUtils.streamToString(inputStream);//streamToString方法:把一个输入流的数据直接转成字符串
  30.         System.out.println(s);
  31.         //关闭相关的流
  32.         inputStream.close();
  33.         bos.close();
  34.         socket.close();
  35.     }
  36. }
复制代码
  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

不到断气不罢休

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表