Java网络编程03:TCP连接


客户端

1、Socket连接服务器

2、发送消息

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端
 */
public class Client {

    public static void main(String[] args) {

        /**
         * 为了可以发送多次消息,将变量定义在最外面
         */
        Socket socket = null;
        OutputStream outputStream = null;

        try {

            /**
             * 1、定义服务端的IP地址和端口号
             */
            InetAddress ip = InetAddress.getByName("127.0.0.1");
            int port = 9999;

            /**
             * 2、创建一个socket连接,传入参数IP地址和端口号
             */
            socket = new Socket(ip, port);

            /**
             * 3、创建输出流发送消息
             * write()方法参数为字节数组
             */
            outputStream = socket.getOutputStream();
            outputStream.write("您好!".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            /**
             * 关闭资源
             */
            if (outputStream != null){

                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (socket != null){

                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

服务端

1、ServerSocket建立服务端口

2、监听客户端Socket连接

3、接收客户端的消息

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 */
public class Server {

    public static void main(String[] args) {

        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;

        try {

            /**
             * 1、设置服务端的端口号,IP地址默认为本地地址
             */
            serverSocket = new ServerSocket(9999);

            while (true) {

                /**
                 * 2、监听客户端连接
                 */
                socket = serverSocket.accept();

                /**
                 * 3、创建输入流读取消息
                 */
                inputStream = socket.getInputStream();

                /**
                 * 4、使用字节数组输出流(管道流),先将所有的字节读取到缓冲区,然后输出,可以避免中文乱码
                 */
                byteArrayOutputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int count;

                while ((count = inputStream.read(buffer)) != -1) {
                    byteArrayOutputStream.write(buffer, 0, count);
                }

                System.out.println(byteArrayOutputStream);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            if (byteArrayOutputStream != null){

                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (inputStream != null){

                try {
                    inputStream.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();
                }
            }
        }
    }
}

文件传输

客户端如果要确保服务端成功收到文件,在监听之前一定要先用shutdownOutput()方法通知服务端已结束传输

客户端

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Client {

    public static void main(String[] args) throws Exception {

        /**
         * 1、创建Socket连接
         */
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);

        /**
         * 2、创建输出流
         */
        OutputStream outputStream = socket.getOutputStream();

        /**
         * 3、读取文件
         */
        FileInputStream file = new FileInputStream("万叶.jpg");

        /**
         * 4、写出文件
         */
        byte[] buffer = new byte[1024];
        int count;

        while ((count = file.read(buffer)) != -1){
            outputStream.write(buffer, 0, count);
        }

        /**
         * 5、通知服务端已经传输完了(只是停止输出,不会断开Socket连接)
         * 如果不加这一步,客户端会进入下面的输入流进行监听,而服务端不知道客户端是否已经结束发送,也会一直监听,陷入死循环
         */
        socket.shutdownOutput();

        /**
         * 6、确保服务端成功接收文件,才能断开连接
         */
        InputStream inputStream = socket.getInputStream();

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer2 = new byte[1024];
        int count2;

        while ((count2 = inputStream.read(buffer2)) != -1){
            byteArrayOutputStream.write(buffer2, 0, count2);
        }

        System.out.println(byteArrayOutputStream);

        /**
         * 7、关闭资源
         */
        byteArrayOutputStream.close();
        inputStream.close();
        file.close();
        outputStream.close();
        socket.close();
    }
}

服务端

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

public class Server {

    public static void main(String[] args) throws Exception {

        /**
         * 1、创建ServerSocket服务端口
         */
        ServerSocket serverSocket = new ServerSocket(9999);

        /**
         * 2、监听客户端连接
         */
        Socket socket = serverSocket.accept();

        /**
         * 3、创建输入流
         */
        InputStream inputStream = socket.getInputStream();

        /**
         * 4、文件输出
         */
        FileOutputStream file = new FileOutputStream("叶宝.jpg");
        byte[] buffer = new byte[1024];
        int count;

        while ((count = inputStream.read(buffer)) != -1){
            file.write(buffer, 0, count);
        }

        /**
         * 5、通知客户端文件接收完毕
         */
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("文件接收完毕".getBytes());

        /**
         * 6、关闭资源
         */
        file.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

Tomcat

前面是手写的服务器(C/S模式),而Tomcat是一款配置好的服务器,可利用它响应HTML页面的访问请求(B/S模式

启动:bin目录下执行startup.bat

乱码问题:conf目录下logging.properties文件,把最后一个UTF-8改为GBK