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

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 机器中,一旦超过保留的套按字范围,数字就会再次从最小的可用数字开始)。
② 套接字建立了一个“专用”连接,它会一直持续到明确断开连接为止,这意味着参与连接的双方都被锁定在通信中,而且无论是
否有数据传递,连接都会连续处于开放状态。从表面看,这似乎是一种合理的连网方式。然而,它也为网络带来了额外的开销。后面会介绍进行连网的另一种方式。采用那种方式,连接的建立只是暂时的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值