Java Swing+Socket程序设计

Swing

Java是不依赖操作系统的语言,它可以在任意平台上运行;依赖于本地平台的组件被称为“重量级组件”,例如AWT;不依赖的称为“轻量级组件”,例如Swing

Swing是Java1.0中基础类AWT(抽象窗口工具箱)的增强组件,但不能完全代替AWT组件,这两个组件需要同时出现在一个GUI中

1
2
import java.awt.*;
import javax.swing.*;

常用窗体

JFrame

可以把JFrame看作承载Swing组件的容器;Swing组件的窗体通常与组件和容器相关,在JFrame对象创建完成后,可用getContentPane()方法将窗体转成容器

Test.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.awt.*;
import javax.swing.*;

public class Test extends JFrame{ //继承JFrame类
public void CreateJFrame(String title){
JFrame jf = new JFrame(title); //创建JFrame对象
Container container = jf.getContentPane(); //获取一个容器
JLabel jl = new JLabel("this is a jf window"); //创建一个JLable标签
jl.setHorizontalAlignment(SwingConstants.CENTER); //设置标签文字居中

container.add(jl); //将标签添加到容器
container.setBackground(Color.WHITE); //设置容器北京颜色
jf.setVisible(true); //使窗体可视
jf.setSize(200, 150); //设置窗体大小
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //设置窗体关闭方式
}

public static void main(String[] args){
new Test().CreateJFrame("Hello world"); //创建一个JFrame窗体
}
}

Socket

通信流程

参考文章:

https://blog.csdn.net/a78270528/article/details/80318571

SocketServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,两边各自用getIputStream()getOutputStream()方法,构造各自的输入输出流,完成所需的会话。通信流程:

1.服务器端

创建ServerSocket对象,绑定监听端口。
通过accept()方法监听客户端请求。
连接建立后,通过输入流读取客户端发送的请求信息。
通过输出流向客户端发送响应信息。
关闭响应的资源。

2.客户端

创建Socket对象,指明需要连接的服务器的地址和端口号。
连接建立后,通过输出流向服务器发送请求信息。
通过输入流获取服务器响应的信息。
关闭相应资源。

3.多线程实现服务器与多客户端之间通信步骤

服务器端创建ServerSocket,循环调用accept()等待客户端连接。
客户端创建一个socket并请求和服务器端连接。
服务器端接受客户端请求,创建socket与该客户建立专线连接。
建立连接的两个socket在一个单独的线程上对话。
服务器端继续等待新的连接。

缓冲区flush

参考文章:

https://blog.csdn.net/lsx991947534/article/details/45065773

flush()这个函数是清空的意思,用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存中,然后再用数据写到文件中,那么当你数据读完时,我们如果这时调用close()方法关闭读写流,这时就可能造成数据丢失,为什么呢,因为,读入数据完成时不代表写入数据完成,一部分数据可能会留在缓存区中,为了理解这个问题,我们举一个例子:

比如,在农村,几乎每家都有抽水机,抽水机的作用是什么呢,就是把水井里的水抽到水缸中,这时我们就会用水管连接抽水机和水缸(水管就好比是缓冲区),当我们想把水井中的水都抽到水缸中时,我们就让抽水机工作抽水,如果我们发现水井里的水刚好抽完时,我们就会关掉抽水机的开关停止抽水,那么这时,管道里就会遗留一部分水,抽水就是读数据,水缸进水就是写数据,水管充当缓存区的角色,不知道这样是不是具象化了呢

那么这样一来我们如果中途调用close()方法,输出区也还是有数据的,就像水缸里有水,只是在缓冲区遗留了一部分,这时如果我们先调用flush()方法,就会强制把数据输出,缓存区就清空了,最后再关闭读写流调用close()就完成了。

JDK中PrintWriter类提供的flush方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class PrintWriter extends Writer {
protected Writer out;
/** Checks to make sure that the stream has not been closed */
private void ensureOpen() throws IOException {
if (out == null)
throw new IOException("Stream closed");
}

/**
* Flushes the stream.
* @see #checkError()
*/
public void flush() {
try {
synchronized (lock) {
ensureOpen(); //ensureOpen()方法是用于确保该流没有被关闭
out.flush();
}
}
catch (IOException x) {
trouble = true;
}
}
}