我昨天在写java网络编程的时候想到这样几个问题,现在总结一下。
一:TCP编程是面向字节流的
我用socket编程,是基于TCP/IP的,而TCP协议是传输层的协议,它是面向连接的,与UDP很大的不同在于前者是面向字节流的协议,而后者是用户数据报协议(User Datagram Protocol
),面向字节流有一个很大的好处,那就是可以进行拥塞控制,进行流量控制,进行差错控制。
为什么UDP不行呢?是因为UDP应用层给传输层什么数据报,传输层就发送什么数据报,根本不管它有多少个字节,传输太多是不是会造成阻塞。而TCP就不一样了,应用层让传输层传输数据的时候,传输层并不会直接发送,而是从缓冲区一个字节一个字节的拿出来,TCP发送端是有发送窗口的,这个窗口就是TCP进行流量控制,差错控制的核心。而接收端又是有接收窗口的,总之通过窗口直接的滑动(或者快了,或者顺序乱了,或者帧丢失了),来进行以上的控制。
那么java在进行socket编程的时候只能使用字节流了?答案并不是这样
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
public class Server1 {
/**服务器端*/
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(5678);
Socket socket = ss.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true)
{
String str=in.readLine();
System.out.println(str);
out.println("hello world");
out.flush();
}
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* socket编程的客户端
* */
public class Client1
public static void main(String[] args)throws Exception{
Socket server=new Socket("localhost",5678);
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));
while(true){
String str=wt.readLine();
out.println(str);
out.flush();
if(str.equals("end")){
break;
}
System.out.println(in.readLine());
}
server.close();
}
}
以上的代码给人一种使用了面向字符流的假象,其实我们可以看到这里的字符流其实是对字节流进行了封装,这里应该是适配器模式,把一个字节流转化成了一个字符流 ,server.getInputStream()方法的源码是,可以看到它实际返回的是字节流。
public InputStream getInputStream() throws IOException
二:print和println的区别到底是什么
在socket编程中,如果使用PrintWriter类作为输出流,那么为什么一定要println(String str),而不是print()。
在我的印象中println只是在print的后面加上一个换行符,估计大部分人跟我的想法一样,可是,看了一下源码发现
/**
* Prints a String and then terminate the line. This method behaves as
* though it invokes <code>{@link #print(String)}</code> and then
* <code>{@link #println()}</code>.
*
* @param x The <code>String</code> to be printed.
*/
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
从上面的两个方法至少可以看到两点1:println方法是线程安全的:2:多了一个newLine()方法。
那么newLine()是个什么方法呢?
/**
private BufferedWriter textOut;
*/
private void newLine() {
try {
synchronized (this) {
ensureOpen();
textOut.newLine();
//在BufferedWriter类中 newLine方法只是写一个换行符
/**
* Writes a line separator. The line separator string is defined by the
* system property <tt>line.separator</tt>, and is not necessarily a single
* newline ('\n') character.
*
* @exception IOException If an I/O error occurs
*
public void newLine() throws IOException {
write(lineSeparator);
}
*/
/**
* Flushes the output buffer to the underlying character stream, without
* flushing the stream itself. This method is non-private only so that it
* may be invoked by PrintStream.
这里的意思是说刷新输出流到存在下面的字符流,而不需要刷新这个流本身
*/
textOut.flushBuffer();
/*
那么这里到底做了什么呢?
*/
charOut.flushBuffer();
if (autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
也就是说println方法比print做的事情多得多。它有终止改行,刷新缓冲区的功能,而print却没有,当使用print输出的时候,没有刷新,也没有终止,而只是单独的写入进去。
那么,刷新一个缓冲区到底在底层是做了什么呢。
分享到:
相关推荐
Java IO是Java编程语言中用于输入/输出操作的重要部分,它提供了一系列的类和方法来处理数据的读写,文件的创建、删除以及流的管理等。以下是对标题和描述中涉及的知识点的详细说明: 1. **文件对象的生成**: 在...
java学习笔记1(java io/nio)设计模式
Java IO流是Java编程语言中处理输入...通过深入学习和理解IO流,开发者可以更好地掌握数据的读取、写入和传输,提升程序的效率和功能。同时,熟悉相关工具和配置文件的使用也能帮助开发者在实际项目中更加得心应手。
### Java IO流学习笔记 #### 异常处理与IO流操作 在进行Java IO流的学习过程中,异常处理是非常重要的一个方面。本节将详细介绍如何在Java中处理异常,并结合具体的IO流操作进行说明。 #### 一、异常处理 在Java...
本学习笔记主要涵盖了Java的基础知识,包括面向对象、集合、IO流、多线程、反射与动态代理以及Java 8的新特性等方面,旨在帮助初学者或有经验的开发者巩固和提升Java编程技能。 1. 面向对象(OOP):Java的核心是...
"Java入门第二季学习笔记"可能深入到更复杂的主题,如异常处理、集合框架、IO流和线程。异常处理是Java中处理错误的重要机制,使得程序更加健壮。集合框架包括ArrayList、LinkedList、HashSet、HashMap等数据结构,...
【Java学习笔记Markdown版】是针对Java初学者和进阶者的一份详尽教程,以Markdown格式编写,便于阅读和整理。Markdown是一种轻量级的标记语言,它允许用户使用易读易写的纯文本格式编写文档,然后转换成结构化的HTML...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(现为Oracle公司的一部分)于1995年发布。...Java学习笔记涵盖了这些核心知识点,通过深入学习和实践,你可以逐步掌握Java编程,并应用于实际项目开发中。
### Java IO流学习笔记 #### 一、IO流的四大抽象类 - **InputStream/OutputStream**:字节的输入输出流的抽象类。 - 数据单位:字节(8比特,范围0-255) - **Reader/Writer**:字符的输入输出流的抽象类。 - ...
"Java学习笔记——良葛格"是一份专为初学者设计的教程资料,由良葛格精心编写,旨在帮助读者掌握JDK5.0版本的Java基础知识。JDK(Java Development Kit)是Java开发的核心工具集,包含了编译器、调试器和运行环境等...
Java开发学习笔记主要针对的是初学者,旨在帮助他们掌握Java编程的基础知识。下面将详细讲解Java开发中的核心概念和步骤。 一、Java环境变量设置 在开始Java编程之前,我们需要安装Java Development Kit (JDK)并...
java基础:IO流学习笔记
"IO-黑马程序员Java学习笔记"这个压缩包包含了关于Java IO的详细教程,可以帮助我们深入理解这个关键领域。下面将根据提供的文件名来解析可能包含的知识点。 1. **IO.md**: 这个文件很可能是Markdown格式的学习...
这份《java学习》笔记包含了多个核心主题,旨在帮助初学者和有经验的开发者深入理解和掌握Java技术。 1. **正则表达式(正则.md)**: 正则表达式在Java中用于文本匹配和搜索,是处理字符串的强大工具。Java提供了...
"Java超强学习笔记"显然是一份全面且深入的Java学习资料,由一位极具洞察力和组织能力的作者精心编纂。这份笔记可能包含了从基础知识到高级特性的全方位讲解,旨在帮助学习者构建坚实的Java编程基础,并提升他们的...