您的位置:首页 > 编程语言 > Java开发

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

2016-06-22 22:15 645 查看

服务器程序

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字符串就可以退出,然后服务器程序等待下一个链接的客户端程序。服务器程序可以循环服务多个用户,但是一时间是只能服务一个客户进程的。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: