Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一。如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的。
Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务端,Socket是建立网络连接时使用的。在建立连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,不因为在服务器或者在客户端而产生不同级别。不管时Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
套接字之间的连接过程可以分分为四个步骤:- 服务器监听;客户端请求服务器;服务器确认;客户端确认;
- 服务器监听:是服务端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
- 客户端请求:是指客户端的套接字提出连接请求,要求连接的目标时服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务端的套接字,指出服务端套接字的地址和端口,然后就向服务端套接字提出连接请求。
- 服务器确认:是指当服务器套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的新的现场,把服务器套接字的描述发给客户端。
- 客户端确认:一旦客户端确认了此描述,连接就建立好了。双方开始通信。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
Socket编程会基于JDK版本的不同而采用不同的形式。
JDK1.5之前为BIO
Block-IO,即阻塞IO实现。
具体看下代码。
Socket服务端代码
package roro.before15.bio;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/*模拟Socket网络编程服务端*/
public class Server {
final static int PROT = 8765;//预定义端口,用来Socket绑定
public static void main(String[] args) {
ServerSocket server = null;//声明Socket服务端
try {
server = new ServerSocket(PROT);//创建Socket服务端
System.out.println(" server start .. ");
//进行阻塞,等待客户端的请求
Socket socket = server.accept();
//新new一个线程执行客户端的请求
new Thread(new ServerHandler(socket)).start();
} catch (Exception e) {
e.printStackTrace();
} finally {//关闭Socket服务端
if(server != null){
try {
System.out.println(" server end .. ");
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
server = null;
}
}
}
客户端代码如下
package roro.before15.bio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/*模拟Socket客户端*/
public class Client {
final static String ADDRESS = "127.0.0.1";
final static int PORT = 8765;
public static void main(String[] args) {
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(ADDRESS, PORT);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
//向服务器端发送数据
out.println("接收到客户端的请求数据...");
String response = in.readLine();
System.out.println("Client: " + response);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();//关闭socket客户端
} catch (IOException e) {
e.printStackTrace();
}
}
socket = null;
}
}
}
服务端业务工作代码如下
package roro.before15.bio;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class ServerHandler implements Runnable{
private Socket socket ;
public ServerHandler(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(), true);
String body = null;
while(true){
body = in.readLine();
if(body == null) break;
System.out.println("Server :" + body);
out.println("服务器端回送响应数据...");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
socket = null;
}
}
}
代码执行运行情况:
1、首先执行服务端,服务端控制台打印:
server start ..
注意、此时服务端处在等待客户请求状态。
2、然后执行服务端,客户端控制台打印:
Client: 服务器端回送响应数据…
最后观察服务端控制台打印:
server start ..
server end ..
Server :接收到客户端的请求数据…
注意、此时服务端 server end 。