网络编程
网络编程,就是在一定的协议下,实现两台计算机的通信的程序。网络传输的TCP/IP协议如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8cde74f94347d933ea2b326cf288b8e8.png)
在java中,“java.net”包中包含提供低层次的通信细节的类和接口。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。
网络编程三要素:
- 协议
1.TCP 协议是一种面向连接的、可靠的协议
2.UDP 协议是一个不可靠的、无连接协议,主要使用于不需要对报文进行排序和流量控制的场合 - IP地址:指互联网协议地址,俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。
- 端口号:网络的通信,本质上是两个进程(应用程序)的通信,端口号就可以唯一标识设备中的进程。端口号的范围为 0~65535,其中 0~1023 的端口号一般固定分配给一些服务。1024~65535的端口号供用户自定义服务使用。
InetAddress类
InetAdress类主要是用于对域名和IP地址相关的一些操作,常用的方法有:
- getByName(String s); //获取Internet上主机的地址
- InetAddress.getLocalHost(); //获取本地机的地址
- getHostName(); //获取主机名
- getHostAddress() //获取主机IP地址
- InetAddress.getByName(String DNS); //通过域名获取主机对象
- InetAddress.getAllByName(String DNS); //通过域名获取主机的所有域名和IP地址
示例如下:
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进行连接,这样,客户端和服务器通过套接字所建立的连接使用输入输出流进行通信。
![](https://i-blog.csdnimg.cn/blog_migrate/d49e64c0257e8c31bb8a163620e9f1f9.png)
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通信步骤:
- 【服务端】启动,创建ServerSocket对象,定义ServerSocket的监听端口,等待连接。
- 【客户端】启动,创建Socket对象,请求连接。
- 【服务端】接收连接,调用accept方法,并返回一个Socket对象。
- 【客户端】Socket对象,获取OutputStream,向服务端写出数据。
- 【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。
- 【服务端】Socket对象,获取OutputStream,向客户端回写数据。
- 【客户端】Scoket对象,获取InputStream,解析回写数据。
- 【客户端】释放资源,断开连接。
应用
- 客户端向服务器发送数据:
1.创建服务器,定义监听端口
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.创建客户端
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();
}
}
运行结果如下,先创建服务器,然后客户端连接服务器向服务器发送了数据
![](https://i-blog.csdnimg.cn/blog_migrate/97ccb0706e41ecdaf69bd60aa3a82323.png)
- 服务器向客户端回写数据
1.创建服务器
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.创建客户端
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();
}
}
运行结果如下,首先创建了服务器,然后创建客户端连接服务器,客户端先向服务器发送数据,然后服务器再回写客户端数据
![](https://i-blog.csdnimg.cn/blog_migrate/091fa0a013dc8293ab503029a2b6ce21.png)