1 什么是Socket编程?
- 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称之为一个Socket。Socket的英文原意是“孔”或者是“插座”。通常也称之为“套接字”,用于描述IP地址和端口,可以用来实现不同计算机之间的通信。每种服务都打开一个Socket,并绑定到一个端口中,不同的端口对应着不同的服务。Socket正如其英文原意那样,像一个多孔插座,一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电,有的提供110伏交流电,有的则提供有线电视节目。客户软件将插头插到不同编号的插座,就可以得到不同的服务。
2 连接过程
- 根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
- 第一步:服务器监听,是服务器套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
- 第二步:客户端请求,是指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
- 第三步:连接确认,是指当服务器端套接字监听到或者接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
3 Java中如何实现Socket编程
- JavaSE中提供了实现Socket编程的API,让网络编程变得更简单,更夹面向对象。实现两台计算机(两个服务)之间的通讯,至少要编写以下的代码: a、服务器端Server.java: i、创建服务器端套接字,表示创建一个服务,并绑定端口号8080。 ii、开始监听网络,准备接收客户端消息,程序在此等待,客户端发送请求之后,接收客户端套接字。 iii、接收客户端消息:
- java.net.Socket类中getInputStream()方法返回这个Socket类对象的字节输入流: v、读取客户端消息: vi、关闭流,关闭客户端套接字和关闭服务器端套接字:
- 自定义Server类的示例代码:
package com.geeklicreed.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket clientSocket = null;
BufferedReader br = null;
try {
//1、创建服务器端套接字对象,表示创建一个服务,并且将该服务绑定到8080端口上
serverSocket = new ServerSocket(8080);
//2、开始监听网络,准备接收客户端的请求,程序在这等待,当客户端发起请求后,接收客户端套接字
clientSocket = serverSocket.accept();
System.out.println("clientSocket:" + clientSocket);
//3、接收client消息
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//4、读取client消息
String temp = null;
while((temp = br.readLine()) != null){
System.out.println(temp);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭客户端套接字
if(clientSocket != null){
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭服务端套接字
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
b、客户端Client.java: i、创建客户端套接字,指向某台电脑的某台服务 ii、发送消息 iii、发送
-
java.net.Socket类中getOutputStream()方法返回这个Socket类对象的字节输出流:
-
java.io.PrintWriter打印字符输出流类中的print(String s)方法:流中输出一个字符串 v、关闭流,关闭客户端套接字
-
自定义Client类的示例代码:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
Socket clientSocket = null;
PrintWriter out = null;
try {
//1、创建客户端套接字,指向某台计算机上的某台服务
clientSocket = new Socket("192.168.0.160",8080);
//2、发送消息
String msg = "Hello World!";
out = new PrintWriter(clientSocket.getOutputStream());
//3、发送
out.print(msg);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
if(out != null){
out.close();
}
//关闭客户端套接字
if(clientSocket != null){
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4 读取的从浏览器发送的HTTP请求协议
上面的客户端程序不再使用 java 代码,我们尝试将“客户端程序”改为“浏览器客户端软件”,编写以下服务器端程序 。
package com.geeklicreed.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
//服务器,接收浏览器client发送的请求
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket clientSocket = null;
BufferedReader br = null;
try {
//1、创建服务器端套接字对象,表示创建一个服务,并且将该服务绑定到8080端口上
serverSocket = new ServerSocket(8080);
//2、开始监听网络,准备接收客户端的请求,程序在这等待,当客户端发起请求后,接收客户端套接字
clientSocket = serverSocket.accept();
System.out.println("clientSocket:" + clientSocket); //打印客户端套接字
//3、接收client消息
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//4、读取client消息
String msgFromClient = null;
while((msgFromClient = br.readLine()) != null){
System.out.println(msgFromClient);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭客户端套接字
if(clientSocket != null){
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭服务端套接字
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
```
- 读取从浏览器中发送的HTTP请求协议:打开 FF 浏览器(标准浏览器),在地址栏上输入以下 URL ,然后敲回,控制台中显示如下内容:
![](http://i2.51cto.com/images/blog/201711/30/a2104cb30630bc7b5ed3c3e88363a602.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
![](http://i2.51cto.com/images/blog/201711/30/fd17f77be2634296f4f0a364fed07488.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)