使用JDK提供的API进行网络通信,会用到Socket,ServerSocket两个类。写个简单的SERVER和CLIENT之间发消息的小程序,竟然发现了挺多的问题。

这是服务器端代码:

package org.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; public class ChatServer { public static void main(String[] args) {
ChatServer server = new ChatServer();
server.start();
} public void start() {
while (true) {
ServerSocket s = null;
Socket socket = null;
try {
s = new ServerSocket(10001);
socket = s.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(),true); String content = in.readLine();
System.out.println(content);
content = content + "1";
out.print(content);
out.flush(); // if not flush, client can't receive data in.close();
out.close(); } catch (IOException e) {
e.printStackTrace();
} finally{
try {
s.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

这是客户端代码:

package org.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException; public class Client {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("128.192.184.93", 10001); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println("hello"); String reply = in.readLine();
System.out.println(reply); in.close();
out.close(); } catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

逻辑很简单:Client会向ChatServer发一个字符串"hello",ChatServer收到后,在这个字符串后面加1,然后发给Client。

这其中遇到了几个问题:

1.PrintWriter构造函数参数autoFlush设置

PrintWriter的构造函数里的第二个参数autoFlush,API文档里解释是:if true, the println,printf, or format methods will flush the output buffer。注意不包括print。

因此,对于ChatServer,32,33行(print),如果不调用flush,Client就收不到数据,尽管在PrintWriter的构造函数里,autoFlush=true;而Client的19行(println),无需调用flush,也能发送数据。

2.Socket的InputStream和OutputStream有关联,如果一个在用,另一个不可关闭

在ChatServer中,如果把35行代码in.close()放到29行之后,30行之前,也就是说,in在读取了数据之后,就关闭掉,造成的后果就是32行代码out.print()失效,这是因为in.close()使socket关闭了,Client只能收到一个null

3.BufferReader的readLine()方法

首先,改方法是阻塞的,如果读不到(即使读到null也算读到),就会阻塞。

该方法会读取一行数据,就是说,读取第一个换行符之前的数据,如果发送的数据中没有换行符,那么,readLine可能会阻塞。

PrintWriter.print()发送的数据中没有换行符,所以多次调用,接受方BufferReader.readLine()读到的数据包括了多次print的数据。

最新文章

  1. js中转移符
  2. IDEA IntelliJ常用设置以及快捷键(转)
  3. hdu3635 Dragon Balls(带权并查集)
  4. quartz使用案例
  5. python中的Unittest常用方法
  6. php 正则表达式
  7. C++之路进阶——优先队列优化最短路径算法(dijkstra)
  8. linux源码Makefile详解(完整)【转】
  9. LabSharp莱博夏普简介
  10. 前端制作篇之meta标签篇
  11. CF670C cinema
  12. ES6学习笔记八(module模块export)
  13. 裸奔的bootloader单步调试
  14. Websphere MQ Cluster
  15. css中display:inline-block display:-moz-inline-box display:-moz-inline-stack 的区别
  16. 开发创建XMPP“发布订阅”扩展(xmpp pubsub extend)
  17. C++ STL 学习笔记__(8)map和multimap容器
  18. tesnorflow实现N个epoch训练数据读取的办法
  19. Eclipse警告:The serializable class XXX does not declare a static final serialVersionUID field of type long
  20. 理解 RESTful 架构(转)

热门文章

  1. jquery.zclip—复制剪贴板(兼容各大浏览器)
  2. 鼠标滑轮一滚动Excel就停止工作
  3. matrix(dp)
  4. 架构设计的UML图形思考
  5. LeetCodeOJ. String to Integer (atoi)
  6. Rabbit.Rpc
  7. docker学习笔记4:利用docker hub上的mysql镜像创建mysql容器
  8. poj2533--Longest Ordered Subsequence(dp:最长上升子序列)
  9. Java基础03 构造器与方法重载
  10. Ch02 从零开始实例学习3