使用jdk的socket通信
使用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的数据。
使用jdk的socket通信的更多相关文章
- Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...
- java Socket通信使用BufferedReader和BufferedWriter的注意事项
注意事项:readLine()要求有换行标识,write()要输出换行标识,要调用flush()刷新缓冲区. 以下是取自java socket通信中的一小段代码. BufferedReader rea ...
- TTMS 一个基于Java Swing的Socket通信的剧院票务管理系统
TTMS (Theater Ticket Management System) 点我进入github TTMS全称剧院票务管理系统,分为客户端和服务器端.服务器端可以接收客户端连接请求,客户端相当于我 ...
- 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?
这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...
- php简单实现socket通信
socket通信的原理在这里就不说了,它的用途还是比较广泛的,我们可以使用socket来做一个API接口出来,也可以使用socket来实现两个程序之间的通信,我们来研究一下在php里面如何实现sock ...
- Socket通信类
package com.imooc; import java.io.BufferedReader; import java.io.IOException; import java.io.InputSt ...
- AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
- socket通信
socket通信 一:socket基于Tcp连接,数据传输有保证 二:socket连接的建立过程: 1:服务器监听 2:客户端发出请求 3:建立连接 4:通信 三:一个简单的例子:服务器端每隔一段时间 ...
- Android之Socket通信、List加载更多、Spinner下拉列表
Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务 ...
随机推荐
- 用QFileSystemWatcher来监视文件和目录的改变(内部还是使用了timer)
Use Case: 两个程序共享同一个Configuration文件,当一个程序作出改变的时候,需要另外一个程序能够及时响应. 之前其实猜的八九不离十,估计是有一个Timer,然后定时查询Config ...
- yii_wiki_204_using-cjuidialog-to-edit-rows-in-a-cgridview(通过CJuiDialog在CGridView中修改行数据)
/*** Using CJuiDialog to edit rows in a CGridView http://www.yiiframework.com/wiki/204/using-cjuidia ...
- JavaScript和JQuery获取DIV的值
1.设计源代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- sass玩转颜色总结笔记
变量: $color:#f00; 1.变浅和加深颜色,sass使用HSL标准来变浅或加深颜色 lighten($color,10%); darken($color,30%); ...
- weblogic公布的项目用途myeclipse正常启动,点击startWeblogic.cmd报错解决方案
今天在做项目中遇到的问题.使用weblogic公布的项目,使用myeclipse正常启动,但点击startWeblogic.cmd会报错.我提出了一个class not found.楚是什么问题.后来 ...
- svn回滚版本2
svn 版本回滚 取消对代码的修改分为两种情况: 第一种情况:改动没有被提交(commit). 这种情况下,使用svn revert就能取消之前的修改. svn revert用法如下: # svn ...
- CVPapers论文整理工具-开源
一.工具介绍及运行实例 相信计算机视觉领域的同道中人都知道这个Computer Vision Resource网站, http://www.cvpapers.com/ 网页部分截图如下: 可以看到有 ...
- 一步一步重写 CodeIgniter 框架 (1) —— url 如何映射到具体的方法
CodeIgniter 框架最显著的特征就是 MVC 模式,它的做法就是提取 url 中的'分段', 映射到某个类的某个方法,从而由该方法来输出最终显示的页面内容.那么我们第一课中就是实现一个这样的原 ...
- Thinkpad W520 完美安装Ubuntu14.04LTS
Thinkpad W520 完美安装Ubuntu14.04LTS Ubuntu已经升级到14.04LTS,这是个长期支持的版本号.自从上次安装12.04LTS之后一直没有升级. 于是从站点上下载Ubu ...
- C#由变量捕获引起对闭包
C#由变量捕获引起对闭包的思考 前言 偶尔翻翻书籍看看原理性的东西确实有点枯燥,之前有看到园中有位园友说到3-6年工作经验的人应该了解的.NET知识,其中就有一点是关于C#中的闭包,其实早之前在看 ...