Java网络编程
网络编程的底层基础-Socket通信

1

Socket通信的一般步骤

  1. 在客户方和服务器方创建Socket/ServerSocket实例;
  2. 打开连接到Socket的输入/输出流;
  3. 利用输入/输出流,按照一定的协议对Socket进行读/写操作;
  4. 关闭输入/输出流。

Socket通信-客户端

java.net.Socket类

Socket构造方法

1
2
public Socket(String host,int port){}
public Socket(InetAddress address,int port){}

从Socket中获得输入输出流

1
2
public InputStream getInputStream()
public OutputStream getOutputStream()

向输出流写,从输入流读

关闭

1
public void close()

Socket通信-客户端例子 端口扫描

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//ch10.SocketScan
//尝试和远程每一个端口连接
package ch10;
import java.io.IOException;
import java.net.Socket;
public class SocketScan {
public SocketScan() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
//远程的地址,可以是IP 地址,也可以是域名
String address = "www.163.com";
for (int port = 80; port < 10000; port++) {
Socket socket =null;
try {
System.out.println("scan "+address +":" + port);
socket = new Socket(address, port);
//远程主机名
System.out.println("hostname=" + socket.getInetAddress().getHostName());
//远程地址
System.out.println("ip=" + socket.getInetAddress().getHostAddress());
System.out.println(address + " listen on port:" + port);
} catch (IOException e) {
System.out.println(address + " port=" + port + " connect error:" + e);
}finally {
if(socket!=null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}

Socket通信-类Socket

2

Socket通信-类ServerSocket

3

Client-Server通讯例子

面向byte

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//ch10.MyClientSocketV1
package ch10;
import java.io.OutputStream;
import java.net.Socket;
/**
* 本例子和 演示了 ch10.MyServerSocketV1配合,演示了如何使用socket 获得 OutputStream,
* 需要在命令行模式下,将当前目录切换到 bin目录下 执行 java ch10.MyServerSocketV1 再打开一个命令行模式,将当前目录切换到
* bin目录下 执行 java ch10.MyClientV1
*/
public class MyClientSocketV1 {
public MyClientSocketV1() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
Socket client = null;
OutputStream out = null;
try {
// 构建远程连接
client = new Socket("127.0.0.1", Config.PORT);
System.out.println("connection " + client.getInetAddress().toString() + " port=" + Config.PORT + " ok!");
// 获得输出流
out = client.getOutputStream();
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
String line = "I say " + i;
System.out.println("From client:" + line);
// 向输出流中写
out.write(line.getBytes());
out.flush();
}
out.write(Config.BYE.getBytes());
out.close();
client.close();
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
} finally {
MyUtil.close(out);
MyUtil.close(client);
}
}
}
//ch10.MyServerSocketV1
package ch10;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 本例子演示了如何使用socket 获得 InputStream,
* 需要在命令行模式下,将当前目录切换到 bin目录下 执行 java ch10.MyServerSocketV1
* 再打开一个命令行模式,将当前目录切换到 bin目录下 执行 java ch10.MyClientV1
*/
public class MyServerSocketV1 {
public static void main(String[] args) {
ServerSocket server=null;
Socket socket=null;
InputStream in =null;
try {
server = new ServerSocket(Config.PORT);
System.out.println("server listen on port:" + Config.PORT + " ok!");
socket = server.accept(); // 等待客户端连接,只能和一个客户端连接
//构造输入流的方式,注意和MyServerSocketV2区别
in = socket.getInputStream();
byte[] data = new byte[Config.MAX_LEN];
int readed = in.read(data);
String line = new String(data, 0, readed);
while (!Config.BYE.equals(line)) {
System.out.println("From server received: " + line);
readed = in.read(data);
line = new String(data, 0, readed);
}
in.close();
socket.close();
server.close();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}finally {
MyUtil.close(in);
MyUtil.close(socket);
MyUtil.close(server);
}
}
}
//服务器端:
ServerSocket server=new ServerSocket(Config.PORT);
Socket socket=server.accept();
InputStream in=socket.getInputStream();
//客户端:
Socket client=new Socket("127.0.0.1",config.PORT);
OutputStream out=client.getOutputStream();

面向char

1
2
3
4
5
6
7
//ch10.MyClientSocketV2
//ch10.MyServerSocketV2
//服务器端:
BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=in.readLine();
//客户端:
PrintWriter out=new java.io.PrintWriter(client.getOutputStream());

支持输入、输出、多客户端

1
2
3
4
5
6
7
//ch10.MyClientSocketV3
//ch10.MyServerSocketV3
while(true){
Socket socket=server.accept();//等待客户端连接
System.out.println("client"+socket.getInetAddress()+" connect ok!");
new ServerThread(socket).start();
}

网络编程

做一个自己的简易浏览器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//ch10.http.HTTPClient
package ch10;
import java.net.*;
import java.io.*;
import java.util.*;
/**
* 实现一个最简陋的浏览器
*/
public class HTTPClient {
public static void main(String args[]) {
Socket socket = null;
String host = "www.tju.edu.cn";
int port = 80;
try {
socket = new Socket(host, port); // 与HTTPServer建立 连接
/* 创建HTTP请求 */
StringBuffer sb = new StringBuffer("GET http://www.tju.edu.cn/index.htm HTTP/1.1\r\n");
sb.append("Accept: */*\r\n");
sb.append("Accept-Language: zh-cn\r\n");
// sb.append("Accept-Encoding: gzip, deflate\r\n");
sb.append("User-Agent: HTTPClient\r\n");
// sb.append("Host: localhost:8080\r\n");
sb.append("Host: www.tju.edu.cn:80 \r\n");
sb.append("Connection: Keep-Alive\r\n\r\n");
/* 发送HTTP请求 */
OutputStream socketOut = socket.getOutputStream(); // 获得输出流
socketOut.write(sb.toString().getBytes());
Thread.sleep(2000); // 睡眠2秒,等待响应结果
/* 接收响应结果 */
InputStream socketIn = socket.getInputStream(); // 获得输入流
int size = socketIn.available();
byte[] buffer = new byte[size];
socketIn.read(buffer);
System.out.println(new String(buffer, "UTF-8")); // 打印响应结果
System.out.println("ok");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

做一个自己的简易WebServer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//ch10.http.HTTPServer
package ch10;
import java.io.*;
import java.net.*;
/**
* 一个 HTTPServer的例子
*/
public class HTTPServer {
public static void main(String args[]) {
int port;
ServerSocket serverSocket;
try {
port = Integer.parseInt(args[0]);
} catch (Exception e) {
System.out.println("port = 8080 (默认)");
port = 8080; //默认端口为8080
}
try {
serverSocket = new ServerSocket(port);
System.out.println("服务器正在监听端口:" + serverSocket.getLocalPort());
while (true) { //服务器在一个无限循环中不断接收来自客户的TCP连接请求
try {
//等待客户的TCP连接请求
final Socket socket = serverSocket.accept();
System.out.println("建立了与客户的一个新的TCP连接,该客户的地址为:"
+ socket.getInetAddress() + ":" + socket.getPort());
service(socket); //响应客户请求
} catch (Exception e) {
e.printStackTrace();
}
} //#while
} catch (Exception e) {
e.printStackTrace();
}
}
/** 响应客户的HTTP请求 */
public static void service(Socket socket) throws Exception {
/*读取HTTP请求信息*/
InputStream socketIn = socket.getInputStream(); //获得输入流
Thread.sleep(500); //睡眠500毫秒,等待HTTP请求
int size = socketIn.available();
byte[] requestBuffer = new byte[size];
socketIn.read(requestBuffer);
String request = new String(requestBuffer);
System.out.println(request); //打印HTTP请求数据
//String contentType = "text/html";
String contentType = "application/zip";
/*创建HTTP响应结果 */
//HTTP响应的第一行
String responseFirstLine = "HTTP/1.1 200 OK\r\n";
//String responseFirstLine = "HTTP/1.1 403 Not Found \r\n";
//HTTP响应头
String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";
//获得读取响应正文数据的输入流
/*发送HTTP响应结果 */
OutputStream socketOut = socket.getOutputStream(); //获得输出流
//发送HTTP响应的第一行
socketOut.write(responseFirstLine.getBytes());
//发送HTTP响应的头
socketOut.write(responseHeader.getBytes());
//发送HTTP响应的正文
String content="hellow "+new java.util.Date().toString();
byte[] buffer = content.getBytes();
socketOut.write(buffer, 0, buffer.length);
Thread.sleep(1000); //睡眠1秒,等待客户接收HTTP响应结果
socket.close(); //关闭TCP连接
}
}

文章源码

文章源码 备用仓库