java实现了简单的Echo服务程序分服务器和客户端

来源:互联网 发布:fpga硬件编程语言 编辑:程序博客网 时间:2024/05/08 19:00

服务器程序

package simple.server;/*所遇到的坑1、现在是服务器和客户端可以建立链接,服务器可以把消息通过输出流发送到客户端显示,但是客户端的数据不可以发送到服务器端显示。然后各种找,代码中加了很多的输出语句,查找现在执行到了哪里。发现服务器程序不能输出客户端发送过来的信息,也不能将信息回显到客户端。找了很久,也在网络找了发现readLine函数是以换行符位返回的判定规则。搜嘎,然后把所有通过流发送调用的write函数后都插入一个换行符。2、在试验发现还不行,找到我的输出流都用了BufferedWriter缓存,write发送之后必须要强制刷新,flush()一下。才算到位啦。真是辛苦。*/import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.ServerSocket;import java.net.Socket;public class Server {    private static final int PORT = 8900;    // 知名端口(0-1023)还会报权限不够的错误。    private ServerSocket serverSocket;    public Server() throws IOException {        this.serverSocket = new ServerSocket(PORT);        System.out.println("服务器启动" + "在" + PORT + "端口监听链接请求");    }    public String echo(String msg) {        return "echo: " + msg;    }//服务器主要的处理逻辑    public void service() {        // Socket socket=null;        while (true) {            Socket socket = null;            try {                System.out.println("开始监听");                socket = serverSocket.accept();                System.out.println("New connection" + "accepted" + socket.getInetAddress() + ": " + socket.getPort());                BufferedReader br = getReader(socket);                BufferedWriter bw = getWriter(socket);                String msg = null;                bw.write(socket.getInetAddress() + ": " + socket.getPort() + "你好\n");                // 强制flush,将数据推送到客户端哪里去。                bw.flush();                System.out.println("获得了输入流和输出流了");                while ((msg = br.readLine()) != null) {    // 服务器读取客户端数据时候readline函数阻塞了,// 如果客户端断开了链接,说明到了流的末尾,将返回null,//或者一串字符串跟着换行符也将不在阻塞,string返回。                    System.out.println("获得了" + socket.getInetAddress() + "数据:" + msg + "\t将回显回去");                    bw.write(echo(msg));//回显                    bw.newLine();// 这个操作也是必须的,相当于插入一个行分割符,readline方法用来判定一行字符串有没结束                    bw.flush();// 刷新输出缓冲区                    if (msg.equals("bye")) {                        System.out.println("链接断开,监听下一次链接");                        break;                    }                }                // (!socket.isClosed()&& socket.isConnected())表示链接还在                if (!(!socket.isClosed() && socket.isConnected())) {                    System.out.println("链接断开,监听下一次链接");                }                // System.out.println("没有进入while循环吗 "+msg);            } catch (IOException e) {            } finally {                try {// 一次链接后把这个socket销毁。等待下一次的                    //socket链接                    if (socket != null)                        socket.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    private BufferedReader getReader(Socket socket) throws IOException {        InputStream ins = socket.getInputStream();        return new BufferedReader(new InputStreamReader(ins, "UTF-8"));    }    private BufferedWriter getWriter(Socket socket) throws IOException {        OutputStream ous = socket.getOutputStream();        return new BufferedWriter(new OutputStreamWriter(ous, "UTF-8"));    }    public static void main(String arg[]) throws IOException {        new Server().service();    }    // 通过这个函数测试后,客户端函数可以发送数据到服务器进程中。发现了客户端那边发送过来时候flush了一下。    public void testClientReader() {        try {            Socket socket = serverSocket.accept();            BufferedReader br = getReader(socket);            System.out.println(br.readLine());        } catch (IOException e) {        }    }}

客户端测试代码

package client.toserver;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;public class ClientDemo {    private static final int PORT = 8900;    private String host = "localhost";    private Socket socket;    public ClientDemo() {        try {            this.socket = new Socket(host, PORT);            System.out.println("客户端链接成功");        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    public static void main(String[] args) {        new ClientDemo().talkToServer();        System.out.println("client over");    }    // 测试写数据到服务器的连通性    public void testServerWriter() {        BufferedWriter bWriter = getWriter(socket);        try {            bWriter.write("vincent ok");            bWriter.newLine();            bWriter.flush();// 这个动作非常重要        } catch (Exception e) {            // TODO: handle exception        }    }    public void talkToServer() {        BufferedReader bReader = getReader(socket);        BufferedWriter bWriter = getWriter(socket);        BufferedReader localbr;        String mString = null;        // 构建本地客户端终端的输入流        try {            localbr = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));            // while (true) {            // if ((mString = localBuRe.readLine()) != null) {            // System.out.println("client print: " + mString);            // bWriter.write(mString);            // System.out.println("Server print: " + bReader.readLine());            // if (mString.equals("bye")) {            // break;            // }            // } else {            // break;            // }            // }            System.out.println("进入while循环");            // System.out.println(bWriter == null ? "true" : "false");            // System.out.println(System.getProperty("line."));            System.out.println("server print  " + bReader.readLine());            while ((mString = localbr.readLine()) != null) {                // readLine方法必须读取到行分割符才返回读取。所以传递给输入流的字符串必须包含行分割符                System.out.println("client print  " + mString);                bWriter.write(mString);                bWriter.newLine();// 插入一个行分隔符,作为服务器端readline函数判断这个字符串结束的标识                // 非常重要的是必须显式的将数据推送到服务器哪里去                bWriter.flush();                System.out.println("输出到server的数据");                // 读取到服务器的数据,readline方法是阻塞的                System.out.println("获得了服务器响应数据: " + "server print  " + bReader.readLine());                if (mString.equals("bye")) {                    socket.close();                    break;                }            }            System.out.println("退出while循环");        } catch (Exception e) {            // TODO: handle exception        } finally {            if (socket != null) {                try {                    socket.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }    }    private BufferedWriter getWriter(Socket socket) {        try {            OutputStream outputStream = null;            BufferedWriter bWriter = null;            outputStream = socket.getOutputStream();            bWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));            return bWriter;        } catch (Exception e) {            // TODO: handle exception        }        return null;    }    private BufferedReader getReader(Socket socket) {        try {            InputStream ins = null;            BufferedReader brReader = null;            ins = socket.getInputStream();            brReader = new BufferedReader(new InputStreamReader(ins, "UTF-8"));            return brReader;        } catch (Exception e) {            // TODO: handle exception        }        return null;    }}

测试结果

在eclipse下开了两个窗口分别运行模拟服务器进程和客户端进程。
左边是发起请求的客户端,右边是服务请求的服务器程序。
客户端程序需要退出交互只要输入bye字符串就可以退出,然后服务器程序等待下一个链接的客户端程序。服务器程序可以循环服务多个用户,但是一时间是只能服务一个客户进程的。
这里写图片描述

0 0
原创粉丝点击