使用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连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务 ...
随机推荐
- m序列产生器
扩频通讯中会用的到伪随机数列 —— m序列 代码中是5bit原始码 module m_generate ( clock , reset , m_code ); input clock ,reset ; ...
- cygrunsrv: Error starting a service: QueryServiceStatus: Win32 error 1062: 解决办法
问题原因:很可能是/var/log的权限设置不正确.首先执行 mkpasswd 和 mkgroup 重新生成权限信息,再删除sshd服务,重新配置 解决办法: $ mkpasswd -l > / ...
- C++的运算符
C++的运算符十分丰富,使得C++的运算十分灵活方便.例如把赋值号(=)也作为运算符处理,这样,a=b=c=4就是合法的表达式,这是与其他语言不同的.C++提供了以下运算符: 算术运算符+(加) - ...
- 六、Nginx 防盗链
盗链是指一个网站的资源(图片或附件)未经允许在其它网站提供浏览和下载.尤其热门资源的盗链,对网站带宽的消耗非常大,本文通过nginx的配置指令location来实现简单的图片和其它类型文件的防盗链. ...
- pyfits 读取bintable
import pyfits as pf import numpy as np import math import pandas as pd import matplotlib.pyplot as p ...
- gethostbyname()函数说明
gethostbyname()函数说明——用域名或主机名获取IP地址 包含头文件 #include <netdb.h> #include <sys/socket.h> ...
- The type MultipartEntity is deprecated
在HttpCient4.3之前上传文件主要使用MultipartEntity这个类,但如今这个类已经不在推荐使用了(过时了).随之替代它的类是MultipartEntityBuilder.关于Mult ...
- <转载>Div+Css布局教程(-)CSS必备知识
目录: 1.Div+Css布局教程(-)CSS必备知识 注:本教程要求对html和css有基础了解. 一.CSS布局属性 Width:设置对象的宽度(width:45px). Height:设置对象的 ...
- Selenium 出现: Caused by: java.lang.ClassNotFoundException: org.w3c.dom.ElementTraversal
webDriver 运行的时候出现: Caused by: java.lang.ClassNotFoundException: org.w3c.dom.ElementTraversal 解决办法: 只 ...
- 更快地从IplImage转换成QImage
转:http://blog.sina.com.cn/s/blog_5c70dfc80100qzif.html 在Qt平台上使用OpenCV肯定会遇到从IplImage到QImage的转换问题,找了很多 ...