网络编程

网络编程,就是在一定的协议下,实现两台计算机的通信的程序。网络传输的TCP/IP协议如下:

在java中,“java.net”包中包含提供低层次的通信细节的类和接口。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。
网络编程三要素:

  • 协议

1.TCP 协议是一种面向连接的、可靠的协议
2.UDP 协议是一个不可靠的、无连接协议,主要使用于不需要对报文进行排序和流量控制的场合

  • IP地址:指互联网协议地址,俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。
  • 端口号:网络的通信,本质上是两个进程(应用程序)的通信,端口号就可以唯一标识设备中的进程。端口号的范围为 065535,其中 01023 的端口号一般固定分配给一些服务。1024~65535的端口号供用户自定义服务使用。

InetAddress类

InetAdress类主要是用于对域名和IP地址相关的一些操作,常用的方法有:

  • getByName(String s); //获取Internet上主机的地址
  • InetAddress.getLocalHost(); //获取本地机的地址
  • getHostName(); //获取主机名
  • getHostAddress() //获取主机IP地址
  • InetAddress.getByName(String DNS); //通过域名获取主机对象
  • InetAddress.getAllByName(String DNS); //通过域名获取主机的所有域名和IP地址
    示例如下:
    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.net.InetAddress;
    import java.net.UnknownHostException;
    import java.util.Arrays;

    public class InetAddressTest {
    public static void main(String[] args) throws UnknownHostException {
    InetAddress localHost = InetAddress.getLocalHost(); //本地主机
    System.out.println(localHost.getHostName()); //主机名字:LAPTOP-8FII27QD
    System.out.println(localHost.getHostAddress()); //主机IP地址:192.168.137.1
    //通过域名获取主机
    InetAddress duHost = InetAddress.getByName("www.baidu.com");
    System.out.println(duHost.getHostName()); //域名:www.baidu.com
    System.out.println(duHost.getHostAddress()); //ip地址:36.152.44.95

    InetAddress[] duHosts = InetAddress.getAllByName("www.baidu.com");
    System.out.println(Arrays.toString(duHosts)); //[www.baidu.com/36.152.44.95, www.baidu.com/36.152.44.96]
    //直接使用IP地址获取主机
    InetAddress remoteHost = InetAddress.getByName("192.168.1.200");
    System.out.println(remoteHost.getHostName());

    }
    }

Socket编程

在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序,简称客户端,而在第一次通讯中等待连接的程序被称作服务器端(Server)程序,简称服务器。

  • Socket类:发送TCP消息。
  • ServerSocket类:创建服务器

套接字是一种进程间的数据交换机制。这些进程既可以在同一机器上,也可以在通过网络连接的不同机器上。 在客户端和服务器中,分别创建独立的Socket,并通过Socket的属性,将两个Socket进行连接,这样,客户端和服务器通过套接字所建立的连接使用输入输出流进行通信。

Socket类

Socket类实现客户端套接字,其构造方法如下:
Socket(String host, int port) :创建套接字对象并将其连接到指定主机host上的指定端口号port。如果指定的host是null ,则相当于指定地址为回送地址。
Socket类的常用方法有:

  • InputStream getInputStream() //返回此套接字的输入流。
  • OutputStream getOutputStream() // 返回此套接字的输出流。
  • void close() //关闭此套接字。
  • void shutdownOutput() // 禁用此套接字的输出流,任何先前写出的数据将被发送,随后终止输出流

注意事项:

  • 关闭生成的InputStream/OutputStream也将关闭相关的Socket
  • 如果此Scoket具有相关联的通道,则生成的OutputStream 的所有操作也关联该通道
  • 一旦一个socket被关闭,它不可再使用
  • 回送地址(127.0.0.1) 是本机回送地址,主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,立即返回,不进行任何网络传输

ServerSocket类

ServerSocket类实现了服务器套接字,其构造方法示例如下:
ServerSocket server = new ServerSocket(4444) //参数为客户端端口号
ServerSocket用到的方法主要是:

  • accept() //一直阻塞直到建立连接

Socket编程的步骤

Socket编程的步骤:

  • 创建服务器ServerSocket对象,定义ServerSocket的监听端口,即构造方法传递的参数。      
  • ServerSocket调用accept()方法,使之处于阻塞状态。      
  • 创建客户端Socket,并设置服务器的IP及端口。      
  • 客户端发出连接请求,建立连接。      
  • 分别取得服务器和客户端Socket的InputStream和OutputStream。      
  • 利用Socket和ServerSocket进行数据传输。      
  • 关闭流及Socket。

TCP通信步骤:

  1. 【服务端】启动,创建ServerSocket对象,定义ServerSocket的监听端口,等待连接。
  2. 【客户端】启动,创建Socket对象,请求连接。
  3. 【服务端】接收连接,调用accept方法,并返回一个Socket对象。
  4. 【客户端】Socket对象,获取OutputStream,向服务端写出数据。
  5. 【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。
  6. 【服务端】Socket对象,获取OutputStream,向客户端回写数据。
  7. 【客户端】Scoket对象,获取InputStream,解析回写数据。
  8. 【客户端】释放资源,断开连接。

应用

  • 客户端向服务器发送数据:

1.创建服务器,定义监听端口

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.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketTest {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动 , 等待连接 .... ");
ServerSocket ss = new ServerSocket(6666);
Socket server = ss.accept();
InputStream is = server.getInputStream();
byte[] b = new byte[1024];
int len = is.read(b);
String msg = new String(b, 0, len);
System.out.println(msg);
is.close();
server.close();
}

}


2.创建客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class socketTest {
public static void main(String[] args) throws Exception {
System.out.println("客户端 发送数据");
Socket client = new Socket("localhost", 6666);
OutputStream os = client.getOutputStream();
os.write("客户端向服务器发送的数据".getBytes());
os.close();
client.close();
}

}

运行结果如下,先创建服务器,然后客户端连接服务器向服务器发送了数据

  • 服务器向客户端回写数据

1.创建服务器

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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动 , 等待连接 .... ");
ServerSocket ss = new ServerSocket(4444);
Socket server = ss.accept();
InputStream is = server.getInputStream();
byte[] b = new byte[1024];
int len = is.read(b);
String msg = new String(b, 0, len);
System.out.println(msg);
OutputStream os = server.getOutputStream();
os.write("服务器向客户端发送的数据".getBytes());
// 7.关闭资源.
os.close();
is.close();
server.close();
}
}

2.创建客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ClientTets {
public static void main(String[] args) throws Exception {
System.out.println("客户端:发送数据");
Socket client = new Socket("localhost", 4444);
OutputStream os = client.getOutputStream();
os.write("客户端向服务器发送的数据".getBytes());
InputStream is = client.getInputStream();
byte[] b = new byte[100];
int len = is.read(b);
System.out.println(new String(b, 0, len));
is.close();
os.close();
client.close();
}
}

运行结果如下,首先创建了服务器,然后创建客户端连接服务器,客户端先向服务器发送数据,然后服务器再回写客户端数据