使用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通信的更多相关文章

  1. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...

  2. java Socket通信使用BufferedReader和BufferedWriter的注意事项

    注意事项:readLine()要求有换行标识,write()要输出换行标识,要调用flush()刷新缓冲区. 以下是取自java socket通信中的一小段代码. BufferedReader rea ...

  3. TTMS 一个基于Java Swing的Socket通信的剧院票务管理系统

    TTMS (Theater Ticket Management System) 点我进入github TTMS全称剧院票务管理系统,分为客户端和服务器端.服务器端可以接收客户端连接请求,客户端相当于我 ...

  4. 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?

    这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...

  5. php简单实现socket通信

    socket通信的原理在这里就不说了,它的用途还是比较广泛的,我们可以使用socket来做一个API接口出来,也可以使用socket来实现两个程序之间的通信,我们来研究一下在php里面如何实现sock ...

  6. Socket通信类

    package com.imooc; import java.io.BufferedReader; import java.io.IOException; import java.io.InputSt ...

  7. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  8. socket通信

    socket通信 一:socket基于Tcp连接,数据传输有保证 二:socket连接的建立过程: 1:服务器监听 2:客户端发出请求 3:建立连接 4:通信 三:一个简单的例子:服务器端每隔一段时间 ...

  9. Android之Socket通信、List加载更多、Spinner下拉列表

    Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务 ...

随机推荐

  1. Qt对话框_模态/非模态

    对话框在Qt GUI应用程序中有着广泛的用途,对话框有模态.非模态两种情况. 对于参数选择的对话框,一般用模态对话框:对于显示或查看某些内容的对话框,一般用非模态对话框. 对话框类QDialog,官方 ...

  2. 基于Sql Server 2008的分布式数据库的实践(二)

    原文 基于Sql Server 2008的分布式数据库的实践(二) 从Win7连接Win2003的Sql Server 2008 1.新建链接服务器链接到Win2003的Sql Server 2008 ...

  3. Spring Boot 探索系列 - 自动化配置篇

    26. Logging Prev  Part IV. Spring Boot features  Next 26. Logging Spring Boot uses Commons Logging f ...

  4. 常用位操作,读8位 I2C 1302 18B20 .

    /*1302*/ unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) { unsigned char i; for(i=8; i>0; ...

  5. IOS 获取网络图像尺寸 更改 图像色彩值 什么一套方法灰色

    直接在代码 头文件 // 图片处理 0 半灰色 1 灰度 2 深棕色 3 反色 +(UIImage*)imageWithImage:(UIImage*)image grayLevelType:(UII ...

  6. 知识点1-1:什么是ASP.NET MVC

    ASP.NET MVC是微软.NET平台上的一个Web开发框架,它为开发者提供了一种构建结构良好的Web应用程序的方式.自2007年首次公布预览以来,作为Web Form的替代品,ASP.NET MV ...

  7. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇] 通过<实现篇>对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding ...

  8. 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)

    该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...

  9. 基于visual Studio2013解决C语言竞赛题之0703乾坤大挪移

       题目

  10. VS2008查看dll导出函数

    打开Visual Studio 2008 命令提示,使用命令 [plain] view plaincopyprint? dumpbin /exports simple.dll 即可查看