网络编程3----TCP简单客户端服务器的实现

服务器的代码:

package network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.spec.RSAOtherPrimeInfo;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {
    private ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动!");
        //采用线程池的目的是建立多个线程,使服务器可以同时处理多个客户端
        ExecutorService service = Executors.newCachedThreadPool();
        while(true){
            //通过accept方法,把内核中已经建立好的连接拿到应用程序中
            //建立连接的细节流程是内核自动完成的,应用程序只需要接收即可
            Socket clientSocket = serverSocket.accept();
            service.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    //通过这个方法,来处理当前的连接
    public void processConnection(Socket clientSocket) throws IOException {
        //首先打印一个日志,说明有客户端已经连上了
        System.out.printf("[%s:%d] 客户端上线 \n",clientSocket.getInetAddress(),clientSocket.getPort());
        //TCP是面向字节流的,同时这里使用try方式,避免后续用完了流对象,忘记关闭
        try(InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()){
            //由于客户端发来的数据,可能是多条数据,针对多条数据,需要采用循环处理
            while(true){
                Scanner scanner = new Scanner(inputStream);
                //没有下一条数据了,说明连接断开了,此时就应该结束循环
                if(!scanner.hasNext()){
                    System.out.printf("[%s:%d] 客户端下线 \n",clientSocket.getInetAddress(),clientSocket.getPort());
                    break;
                }
                //1、读取请求并解析,此处使用next方式作为读取请求的方式,next的规则是,读到”空白符“就返回
                String request = scanner.next();
                //2、根据请求,计算响应
                String response = process(request);
                //3、把响应写回到客户端
                //可以把String转成字节数组,写入到outputstream
                //此处使用PrintWriter包裹outputstream,来写入字符串
                PrintWriter printWriter = new PrintWriter(outputStream);
                //此处的println不是打印到控制台了,而是写入到outputStream对应的流对象中,也就是写入到clientSocket里面
                //自然这个数据也就通过网络发送出去了(发给客户端)
                //此处的println带有\n,也是为了后续客户端这边可以使用scanner.next()来读取数据
                printWriter.println(response);
                //此处记得刷新缓冲区,如果不刷新,数据可能仍然在内存中,没有写入网卡
                printWriter.flush();
                //打印这次交互的内容
                System.out.printf("[%s:%d] req=%s,resq=%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                //processConnection是在处理一个连接,这个方法执行完毕后,连接也就处理完了,所以此时要断开连接
                clientSocket.close();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    public String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}

客户端的代码:

package network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    private Socket socket = null;

    public TcpEchoClient(String serverIp,int serverPort) throws IOException {
        //需要在创建socket的同时,和服务器建立连接,此时就得告诉socket服务器在哪里
        //建立连接的细节,不需要我们手动干预,是内核自动负责的
        //当我们new这个对象的时候,操作系统内核,就开始进行“三次握手”具体细节,完成建立连接的工作
        socket = new Socket(serverIp,serverPort);
    }

    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        try(InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream()){
            PrintWriter writer = new PrintWriter(outputStream);
            Scanner scannerNetwork = new Scanner(inputStream);
            while(true){
                System.out.print("->");
                String request = scanner.next();
                writer.println(request);
                writer.flush();
                String response = scannerNetwork.next();
                System.out.println(response);
            }
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);
        client.start();
    }
}

运行结果截图:

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NBSW001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值