Java编程思想之网络编程(二)套接字Socket

xiaoxiao2021-02-28  13

1 套接字

针对一个特定的连接,每台机器上都有一个“套接字”,可以想象它们之间有一条虚拟的“线缆”。线缆的每一端都插入一个“套接字”或者“插座”里。 “套接字”或者“插座”(Socket)也是一种软件形式的抽象,用于表达两台机器间一个连接的“终端”。抽象的基本宗旨是让我们尽可能不必知道那些细节。

2 套接字类

两个基于数据流的套接字类: ① ServerSocket,服务器用它“侦听”进入的连接;,ServerSocket 的主要任务是在那里耐心地等候其他机器同它连接,再利用accept()方法返回一个实际的Socket。 ② Socket,客户用它初始一次连接。 ③ 创建一个ServerSocket 时,只需为其赋予一个端口编号。不必把一个IP 地址分配它,因为它已经在自己代表的那台机器上了。但在创建一个Socket 时,却必须同时赋予IP 地址以及要连接的端口编号(另一方面,从ServerSocket.accept()返回的Socket 已经包含了所有这些信息)。

3.一个简单的服务器和客户机程序

服务端程序: package com.dason.getip; import java.io.*; import java.net.*; // 服务器的全部工作就是等候建立一个连接 public class DasonServerSocket { // Choose a port outside of the range 1-1024: public static final int PORT = 8080; public static void main(String[] args)throws IOException { // 1.创建一个ServerSocket 时,只需为其赋予一个端口编号 ServerSocket s = new ServerSocket(PORT); System.out.println("ServerSocket: " + s); try { // 2.ServerSocket “侦听”进入的连接,方法会暂时陷入停顿状态(堵塞), // 直到某个客户尝试同它建立连接,通过accept()方法返回一个对应的服务器端套接字 Socket socket = s.accept(); try { System.out.println("Connection accepted: "+ socket); //Socket[addr=127.0.0.1,port=57466,localport=8080] //这意味着服务器刚才已接受了来自127.0.0.1 这台机器的端口57466 的连接,同时监听自己的本地端口8080 // 3. 然后用那个连接产生的Socket 创建一个InputStream 以及一个OutputStream BufferedReader in =new BufferedReader(new InputStreamReader( socket.getInputStream())); // Output is automatically flushed by PrintWriter: /* 对输出来说,使用Writer 方式具有明显的优势。这一优势是通过PrintWriter 表现出来的, * 它有一个过载的构建器,能通过第二个参数一个布尔值标志, * 指向是否在每一次println()结束的时候自动刷新输出*/ PrintWriter out =new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true); // 4.它从InputStream 读入的所有东西都会反馈给OutputStream,直到接收到行中止(END)为止 while (true) { String str = in.readLine(); if (str.equals("END")) { break; } System.out.println("Echoing: " + str); out.println(str); } // 5.最后关闭连接 } finally { System.out.println("closing..."); socket.close(); } } finally { s.close(); } } } 客户端程序: package com.dason.getip; import java.io.*; import java.net.*; public class DasonClientSocket { public static void main(String[] args) throws IOException { // 1. 获得本地主机IP地址的InetAddress 的三种途径 InetAddress addr = InetAddress.getByName(null); // InetAddress addr = InetAddress.getByName("127.0.0.1"); // InetAddress addr = InetAddress.getByName("localhost"); System.out.println("addr = " + addr); //2. 创建客户端套接字 Socket socket = new Socket(addr, DasonServerSocket.PORT); // Guard everything in a try-finally to make // sure that the socket is closed: try { System.out.println("socket = " + socket); //socket: Socket[addr=/127.0.0.1,port=8080,localport=57466] //这意味着客户已用自己的本地端口57466 与127.0.0.1 机器上的端口8080 建立了 连接 BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); // Output is automatically flushed by PrintWriter: PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true); for(int i = 0; i < 10; i ++) { out.println("howdy " + i); String str = in.readLine(); System.out.println(str); } out.println("END"); // 3.关闭连接 } finally { System.out.println("closing..."); socket.close(); } } } 注意: ① 每次重新启动客户程序的时候,本地端口的编号都会增加。这个编号从1025(刚好在系统保留的1-1024 之外)开始,并会一直增加下去,除非我们重启机器。若重新启动机器,端口号仍然会从1025 开始增值(在Unix 机器中,一旦超过保留的套按字范围,数字就会再次从最小的可用数字开始)。 ② 套接字建立了一个“专用”连接,它会一直持续到明确断开连接为止,这意味着参与连接的双方都被锁定在通信中,而且无论是 否有数据传递,连接都会连续处于开放状态。从表面看,这似乎是一种合理的连网方式。然而,它也为网络带来了额外的开销。后面会介绍进行连网的另一种方式。采用那种方式,连接的建立只是暂时的。
转载请注明原文地址: https://www.6miu.com/read-450171.html

最新回复(0)