软件创新实验室:TCP

实现聊天

客户端

  1. 连接服务器Socket
  2. 发送消息,
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

//客户端
public class TcpClient {
    
    
    public static void main(String[] args) {
    
    
       Socket socket = null;
       OutputStream os = null;

       try {
    
    
           //1. 要知道服务器的地址和端口号
           InetAddress serverIP = InetAddress.getByName("127.0.0.1");
           int port = 9999;

           //2. 创建一个socket连接
           socket = new Socket(serverIP, port);

           //3. 发送消息 IO流
           os = socket.getOutputStream();
           os.write("Hello World, this is TCP!".getBytes());
       } catch (Exception e) {
    
    
           e.printStackTrace();
       } finally {
    
    
           if (os != null){
    
    
               try {
    
    
                   os.close();
               } catch (IOException e) {
    
    
                   e.printStackTrace();
               }
           }

           if (socket != null){
    
    
               try {
    
    
                   socket.close();
               } catch (IOException e) {
    
    
                   e.printStackTrace();
               }
           }
       }
    }
}

服务端

  1. 建立服务的端口ServerSocket
  2. 等待用户的链接accept
  3. 接收用户的消息,
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//服务端
public class TcpServer {
    
    
    public static void main(String[] args) {
    
    
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;

        try {
    
    
            //1. 需要一个地址
            serverSocket = new ServerSocket(9999);

            //2. 等客户端连接过来
            socket = serverSocket.accept();

            //3. 读取客户端的信息
            is = socket.getInputStream();

            //管道流
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len=is.read(buffer)) != -1){
    
    
                baos.write(buffer,0,len);
            }

            System.out.println(baos.toString());
        }catch (IOException e){
    
    
            e.printStackTrace();
        } finally {
    
    
            //关闭资源
            if (baos != null){
    
    
                try {
    
    
                    baos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }

            if (is != null){
    
    
                try {
    
    
                    is.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }

            if (socket != null){
    
    
                try {
    
    
                    socket.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }

            if (serverSocket != null){
    
    
                try {
    
    
                    serverSocket.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

说明

代码运行时,要先启动服务端再启动客户端,不然会报错,
在这里插入图片描述

运行结果

服务端启动,

客户端启动,
在这里插入图片描述
 

不难发现,服务端一开始是什么都没有的,在客户端启动后,即客户端向服务端发送消息后,服务端接收到了消息,并显示在了控制台上,

上述操作的服务端只能实现一次接收客户端的消息,

可以对服务端添加while循环使得能接收多次消息,改动如下:

扫描二维码关注公众号,回复: 13404536 查看本文章
//1. 需要一个地址
serverSocket = new ServerSocket(9999);

while (true){
    
    
    //2. 等客户端连接过来
    socket = serverSocket.accept();

    //3. 读取客户端的信息
    is = socket.getInputStream();

    //管道流
    baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len=is.read(buffer)) != -1){
    
    
        baos.write(buffer,0,len);
    }

    System.out.println(baos.toString());
}


 

文件上传

文件上传功能类似于聊天功能的操作,

基本实现

基本实现了文件上传的功能,但还是有点缺陷,没有很好的遵循三次握手,四次挥手原则,

客户端

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

//客户端
public class TcpClient {
    
    
    public static void main(String[] args) throws Exception{
    
    
       //1. 创建一个Socket连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),8888);

       //2. 创建一个输出流
        OutputStream os = socket.getOutputStream();

       //3. 读入文件
        FileInputStream fis = new FileInputStream(new File("A.png"));

       //4. 写出文件
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer)) != -1){
    
    
            os.write(buffer,0,len);
        }

        //5. 关闭资源
        fis.close();
        os.close();
        socket.close();
    }
}

服务端

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//服务端
public class TcpServer {
    
    
    public static void main(String[] args) throws Exception{
    
    
        //1. 创建服务端
        ServerSocket serverSocket = new ServerSocket(8888);

        //2. 监听客户端的连接
        Socket socket = serverSocket.accept();  //阻塞式监听,会一直等待客户端发送信息

        //3. 获取输入流
        InputStream is = socket.getInputStream();

        //4. 文件输出
        FileOutputStream fos = new FileOutputStream(new File("B.png"));
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1){
    
    
            fos.write(buffer,0,len);
        }

        //5. 关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

优化上传

客户端

相比于上面的客户端代码,应做如下的优化:

  • 客户端将文件上传给服务端后,应该告诉服务器上传结束
  • 确认服务端接收完毕后,才能断开连接
 //通知服务端,上传完毕
socket.shutdownOutput();    //客户端已传输完毕

//确定服务端接收完毕后,才能断开连接
InputStream inputStream = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[2048];
int len2;
while ((len2 = inputStream.read(buffer2)) != -1){
    
    
    baos.write(buffer2,0,len2);
}

System.out.println(baos.toString());

服务端

相比于上面的服务端代码,应做如下的优化:

  • 服务端接收完毕后,给客户端一个回显,表示已经接收完毕
//通知客户端我已经接收完毕
OutputStream os = socket.getOutputStream();
os.write("我已经接收完毕,你可以断开连接了!".getBytes());

运行结果

程序运行前,只有两个类TcpServerTcpClient,以及一张图片A.png


 

按照步骤,先运行服务端,在运行客户端,

不难发现在客户端获得回显,
在这里插入图片描述

服务端成功的输出了B.png文件,

猜你喜欢

转载自blog.csdn.net/weixin_46263782/article/details/115428383