学习Mina2(知识准备 - socket - 1)

做Java编程这么多年了,今天学习mina框架的时候,确发现自己连socket编程都不太了解,真是愧对这几年的Java学习经验了。所以在学习mina2前,我首选尝试者了解一下socket。

1. 先摸索个例子程序

实现功能概述:客户端向服务端发送一个命令,服务端接受,并发消息给客户端证明已经收到。如果输入“end”(不区分大小写)测试结束。

1.1 socket服务端
public class CmdServer {
	public static final Log LOG = LogFactory.getLog(CmdServer.class);

	public static final int SERVER_PROT = 8100;
	private static final CmdServer cmdServer = new CmdServer();

	private ServerSocket server;

	private CmdServer() {
		try {
			server = new ServerSocket(SERVER_PROT);
		}
		catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}

	public static CmdServer getServer() {
		return cmdServer;
	}

	public void receiveCmd() {
		LOG.info(">>>接受命令开始...");
		BufferedReader reader = null;
		PrintWriter writer = null;
		try {
			Socket client = server.accept();
			reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
			writer = new PrintWriter(client.getOutputStream());
			while (true) {
				String cmd = reader.readLine();
				writer.print("roger : " + cmd + "\n");
				LOG.info("roger : " + cmd);
				writer.flush();
				if (StringUtils.endsWithIgnoreCase("end", cmd)) {
					break;
				}
			}
			client.close();
		}
		catch (IOException e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
		finally {
			IOUtils.closeQuietly(reader);
			IOUtils.closeQuietly(writer);
		}
		LOG.info("<<<接受命令结束");
	}
}

public class RunSocketServer {

	public static void main(String[] args) {
		CmdServer server = CmdServer.getServer();
		server.receiveCmd();
	}

}

1.2 socket客户端
public class CmdClient {
	public static final Log LOG = LogFactory.getLog(CmdClient.class);

	private Socket server;
	
	public CmdClient() {
		try {
			server = new Socket(InetAddress.getLocalHost(), CmdServer.SERVER_PROT);
		}
		catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}

	public void writeCmd() {
		LOG.info(">>>写命令开始...");
		Scanner scanner = new Scanner(System.in);
		BufferedReader reader = null;
		BufferedWriter writer = null;
		try {
			reader = new BufferedReader(new InputStreamReader(server.getInputStream()));
			writer = new BufferedWriter(new OutputStreamWriter(server.getOutputStream()));
			while (true) {
				String cmd = scanner.nextLine();
				LOG.info("input:" + cmd);
				writer.write(cmd + "\n");
				writer.flush();
				if (StringUtils.endsWithIgnoreCase("end", cmd)) {
					break;
				}
				LOG.info(reader.readLine());
			}
			server.close();
		}
		catch (Exception e) {
			LOG.error(e.getMessage(), e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
		finally {
			scanner.close();
			IOUtils.closeQuietly(reader);
			IOUtils.closeQuietly(writer);
		}
		LOG.info(">>>写命令结束");
	}
}

public class RunSocketClient {

	public static void main(String[] args) {
		CmdClient client = new CmdClient();
		client.writeCmd();
	}
}


2 总结
这么简单的一个程序,需要多久才能够调通呢?对我这样的菜鸟来说折腾了很久。

2.1 遇到的问题和解决方法
  • 感觉只能从客户端写一行字符串,然后程序就戛然而止
  • 首选我怀疑是用控制台输入的问题,开始使用的是System.in来包装BufferedReader,所以就查了一些资料,发现可以在JDK5下面可以使用 Scanner scanner = new Scanner(System.in);(参考 http://www.mkyong.com/java/how-to-read-input-from-console-java/)。使用原始的bufferReader时无法循环的读取输入。
  • 终于可以多行了,但是服务器端不是实时接收到的,只有调用close的时候才收到
  • 发现当客户端程序运行到 LOG.info(reader.readLine());时,就运行不下去了。
    于是注释这句试试,发现可以运行,但是服务器端貌似不是实时的输出,开始怀疑是socket缓存的问题(参考 http://blog.sina.com.cn/s/blog_616e189f0100s3px.html)。但是无论我怎么调整服务器端和客户端的缓存的大小,都是无法解决。
    最后发现是程序是读取一行的,但是我写入数据的时候没有分行符 "\n"导致的。加上分行符,问题解决了

2.2 学习到了什么?
  • 认识了什么是Socket,以及socket的基本实现
  • 认识了socket中还有缓存需要注意的地方
  • 了解了从控制台中读取输入的另外一种方法

3. 下面我们会干点什么?
  • 上面的程序只能连接一次,服务就关闭了,应该改进一下
  • 多个客户端连接到服务器端,怎么交互呢

你可能感兴趣的:(java,socket,Mina)