Fork me on GitHub

java-网络编程


网络编程本质还是在处理IO流上。

InetAddress类

这个类主要用来表示IP地址,有两个子类:Inet4Address和Inet6Address

1
2
3
4
5
6
7
8
9
10
11
import java.net.InetAddress;
public class InetAddressDemo {
public static void main(String[] args) throws Exception{
InetAddress locAdd = InetAddress.getLocalHost();
InetAddress remAdd = InetAddress.getByName("luxuantao.github.io");
System.out.println("本机IP地址"+locAdd.getHostAddress());
System.out.println("我的博客的IP地址"+remAdd.getHostAddress());
System.out.println("本机是否可达"+locAdd.isReachable(5000));
}
}

URL类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.net.URL;
//URL类的基本方法
public class ParseURL {
public static void main(String[] args) throws Exception{
URL Aurl = new URL("http://java.sun.com:80/docs/books/"); //基地址
URL tuto = new URL(Aurl,"tutorial.intro.html#DOWNLOADING"); //相对地址
System.out.println("协议信息"+tuto.getProtocol());
System.out.println("地址"+tuto.getHost());
System.out.println("文件名"+tuto.getFile());
System.out.println("端口"+tuto.getPort());
System.out.println("引用信息"+tuto.getRef());
System.out.println("查询信息"+tuto.getQuery());
System.out.println("路径"+tuto.getPath());
System.out.println("用户信息"+tuto.getUserInfo());
System.out.println("权限信息"+tuto.getAuthority());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
//从URL读取网络资源
public class URLReader {
public static void main(String[] args) throws Exception {
URL tire = new URL("https://luxuantao.github.io/");
BufferedReader in = new BufferedReader(new InputStreamReader(tire.openStream()));
String inputLine;
while((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
in.close();
}
}

URLConnection类

URL是单向的,而URLConnection是双向的,可以通过它对URL资源读或写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
//与指定URL建立动态链接,可向服务器发送请求
public class URLConnectionDemo {
public static void main(String[] args) throws Exception{
URL url = new URL("http://www.mldnjava.cn");
URLConnection urlCon = url.openConnection(); //建立连接
System.out.println("内容大小"+urlCon.getContentLength());
System.out.println("内容类型"+urlCon.getContentType());
BufferedReader in = new BufferedReader(new InputStreamReader((urlCon.getInputStream())));
String inputline;
while ((inputline = in.readLine()) != null) {
System.out.println(inputline);
}
in.close();
}
}

服务端与客户端简单交互

单向传输(服务端给客户端)

示例:服务端传输helloworld给客户端。

客户端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class HelloClient {
public static void main(String[] args) throws UnknownHostException, IOException{
Socket client = new Socket("localhost",8888);
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String context = br.readLine();
System.out.println("当前服务端输出的语句是:"+context);
br.close();
client.close();
}
}

服务端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class HelloServer {
public static void main(String[] args) throws IOException{
ServerSocket server = new ServerSocket(8888);
System.out.println("服务器运行,等待客户端连接");
Socket client = server.accept();
OutputStream out = client.getOutputStream();
PrintWriter pw =new PrintWriter(out);
pw.println("hello world!");
pw.close();
client.close();
server.close();
}
}

一对一TCP传输(单个服务端和单个客户端)

示例:客户端发送半径给服务端,服务端算出圆的面积后把结果返回给客户端。

客户端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.rmi.UnknownHostException;
import java.util.Scanner;
public class RadiusClient {
public static void main(String[] args) throws UnknownHostException, IOException{
Socket client = new Socket("localhost",8888);
Scanner sc = new Scanner(System.in);
DataInputStream fromServer = new DataInputStream(client.getInputStream());
DataOutputStream toServer = new DataOutputStream(client.getOutputStream());
while (true) {
System.out.println("请输入半径:");
double radius = sc.nextDouble();
toServer.writeDouble(radius);
toServer.flush();
double area = fromServer.readDouble();
System.out.println("客户端:输入的半径是:"+radius);
System.out.println("客户端:收到的圆的面积是:"+area);
}
}
}

服务端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class RadiusServer {
public static void main(String[] args) throws IOException{
ServerSocket server = new ServerSocket(8888);
System.out.println("服务器启动成功,时间是"+new Date());
Socket client = server.accept();
DataInputStream inputFromClient = new DataInputStream(client.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(client.getOutputStream());
while(true) {
double radius = inputFromClient.readDouble();
double area = radius*radius*Math.PI;
System.out.println("服务端:接受到客户端半径为:"+radius);
System.out.println("服务端:计算面积为:"+area);
outputToClient.writeDouble(area);
}
}
}

一对多TCP传输(单个服务端和多个客户端)

当多个客户端同时对服务器发送请求时,上面的方法就不行了(在IDE上的表现就是多次启动了客户端程序,这时只有第一个客户端程序能够成功连接上服务端)。

不过,可以通过多线程解决这个问题。

客户端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.rmi.UnknownHostException;
import java.util.Scanner;
public class RadiusClient {
public static void main(String[] args) throws UnknownHostException, IOException{
Socket client = new Socket("localhost",8888);
Scanner sc = new Scanner(System.in);
DataInputStream fromServer = new DataInputStream(client.getInputStream());
DataOutputStream toServer = new DataOutputStream(client.getOutputStream());
while (true) {
System.out.println("请输入半径:");
double radius = sc.nextDouble();
toServer.writeDouble(radius);
toServer.flush();
double area = fromServer.readDouble();
System.out.println("客户端:输入的半径是:"+radius);
System.out.println("客户端:收到的圆的面积是:"+area);
}
}
}

服务端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class RadiusServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888);
System.out.println("服务器启动成功,时间是"+new Date());
while(true) {
Socket client = server.accept();
Thread thread = new Thread(new AreaRunnable(client)); //多创建一个线程回应请求
thread.start();
}
}
}

AreaRunnable类(处理每个线程):

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
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class AreaRunnable implements Runnable {
private Socket client;
public AreaRunnable(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
DataInputStream inputFromClient = new DataInputStream(client.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(client.getOutputStream());
while (true) {
double radius = inputFromClient.readDouble();
double area = radius * radius * Math.PI;
System.out.println("服务端:接受到客户端半径为:" + radius);
System.out.println("服务端:计算面积为:" + area);
outputToClient.writeDouble(area);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

以上这些内容基本上都属于TCP(要先进行服务端与客户端的连接),而实际上现在用的更多的是UDP(非连接,直接发送数据包),今后有空再研究了。

donate the author