网络编程
1.网络通信概述
(1)网络编程中的两个要素
①IP和端口号
②网络通信协议:TCP/IP协议–应(表、会)、传、网、数、物
(2)IP地址(唯一标识)–Java中InetAddress类代表IP,用来封装一个IP地址
1.IP地址的分类
分类方式一:
IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已 经用尽。以点分十进制表示,如192.168.0.1
IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示, 数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
分类方式二:
公网地址(万维网使用)和私有地址(局域网使用)。192.168. 开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机 构内部使用
注:
1.Internet上的主机有两种方式表示地址:①域名(hostName):www.atguigu.com ②IP 地址(hostAddress):202.108.35.210
2.DNS–域名解析服务器
3.本地回路地址:127.0.0.1 对应域名为–localhost
2.实例化InetAddress及常用方法
1.InetAddress InetAddress.getByName("主机号或域名")--造对象
2.InetAddress InetAddress.getLocalHost()--获取本机IP地址
3.String 对应变量.getHostName()--获取指定ip地址的主机名。如果是本机则是计算机名,否则为主机名,如果没有域名则是ip地址
4.String 对应变量.getHostAddress()--获得原始ip地址,返回值是字符串格式
public class test {
public static void main(String[] args) {
//InetAddress没有提供公共的构造器来让我们造对象,我们可以使用InetAddress.getByName("主机号或域名")来造对象
try {
InetAddress byAddress = InetAddress.getByName("192.168.11.14");
InetAddress byName = InetAddress.getByName("www.baidu.com");
//InetAddress.getLocalHost();获取本机IP地址
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(byAddress);
System.out.println(byName);
System.out.println(localHost);
System.out.println("ip地址:"+localHost.getHostAddress());
System.out.println("主机名:"+localHost.getHostName());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
(3)端口号
1.说明
端口号标识正在计算机上运行的进程(程序)
1.不同的进程有不同的端口号被规定为一个 16 位的整数 0~65535。
2。端口分类:
(1)公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
(2)注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
(3)动态/私有端口:49152~65535。
(4)端口号与IP地址的组合得出一个网络套接字:Socket。
2.TCP协议的网络编程
客户端服务器连接过程
客户端:
1.创建socket对象指明服务器端ip和端口号
2.获取输出流用于数据数据
3.写数据
4.资源关闭
服务器端:
1.创建ServerSocket指明自己的端口号
2.调用accept方法接口来自客户端的socket
3.获取输入流
4.读取输入流中的数据,并进行相关操作
5.资源关闭
常用构造器及方法
一、服务器端ServerSocket:负责监听某台计算机的某个端口号,创建对象后调用accept方法接收来自客户端的请求,然后使用getInputStream产生输出流,并对流进行相关操作(可以使用ByteArrayOutputStream来写入)
1.ServerSocket serverSocket = new ServerSocket(0~65535,int bakclog,InetAddress ba)--用于创建一个服务器程序。指定一个服务器明自己的端口号范围0~65535(如果端口号为0则系统会分配一个空闲的端口号);backlog用于指定保持连接请求的等待客户数量,不写默认为50;ba用于为多个网卡和多个ip的指定,一般使用的很少
2.Socket serverSocket.accept()--用来接口来对应端口号自客户端的socket。在客户端连接之前一直处于阻塞状态,如果有客户端连接就会返回一个与之对应的socket对象
3.InetAddress serverSocket/socket(调用accpet后的变量).getInetAddress()--返回一个InetAddress对象,该对象中封装了ServerSocket绑定的IP地址
4.boolean serverSocket.isClosed--用于判断ServerSocket是否为关闭状态(关:TRUE,开:false)
5.void serverSocket.bind(SocketAddress endpoint)--将serverSocket对象绑定到指定IP地址和端口号,endpoint封装了IP地址和端口号
二、客户端socket:实例化后用getOutputStream并调用write(String.getbytes())方法在write中来写相关内容
1.Socket socket = new Socket(InetAddress host, 8899)--主机号,端口号(与要链接的服务器一致)
2.socket.getInputStream、getOutPutStream用于获取输入流和输出流,读取客户端或服务器端接收的数据与向客户端或服务器端发送数。因为客户端与服务器建立连接后数据是以IO流的形式进行交互的。
3.int getPort()--返回socket对象与服务器端连接的端口号
4.InetAddress getLocalAddress()--返回socket对象绑定的本地ip地址
5.void close()--关闭通信
6.socket.getInputStream()--关闭数据的输入
7.socket.getOutputStream()--关闭数据的输出
练习1.客户端与服务器之间通讯
//先运行服务器在运行客户端,端口号一样
@Test
public void cilent() {
Socket socket = null;
OutputStream os = null;
try {
InetAddress in = InetAddress.getByName("127.0.0.1");
//指明IP地址以及服务器的端口号
socket = new Socket(in, 8899);
//进行流的传输
os = socket.getOutputStream();
os.write("你好我是客户端MM".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void server() {
ServerSocket serverSocket = null;
Socket accept = null;
InputStream is = null;
ByteArrayOutputStream bos = null;
try {
serverSocket = new ServerSocket(8899);
accept = serverSocket.accept();
is = accept.getInputStream();
//不建议这样写,因为汉字站3个字节,可能不能放到一个数组中而导致乱码
// byte[] b = new byte[1024];
// int len;
// while ((len = is.read(b)) != -1) {
// String s = new String(b, 0, len);
// System.out.println(s);
// }
//在使用ByteArrayOutputStream存放字符串时,每一个数组暂时先不做处理,等到把所有的数据都拿到把各个数组都拼起来在做处理,因此不会出现乱码
bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1) {
bos.write(b, 0, len);
}
//输出bos中的所有的数据--即byte数组
System.out.println(bos.toString());
System.out.println("收到了来自于" + accept.getInetAddress().getHostAddress() + "的数据");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (accept != null) {
accept.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
练习2.客户端发送文件给服务端,服务端将文件保存在本地。输入流拿到要读取文件,输出流写文件,在读取和写时使用对应流的读和写方法进行拷贝,服务器给客户端传输图片已接收的信息
@Test
public void cilents() {
Socket socket = null;
OutputStream os = null;
FileInputStream fis = null;
ByteArrayOutputStream baos = null;
InputStream inputStream = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
os = socket.getOutputStream();
fis = new FileInputStream("test.jpg");
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != -1) {
os.write(b, 0, len);
}
//socket.getInputStream()关闭数据的输出
socket.shutdownOutput();
inputStream = socket.getInputStream();
byte[] b1 = new byte[1024];
int len1;
baos = new ByteArrayOutputStream();
while ((len1 = inputStream.read(b1)) != -1) {
baos.write(b1, 0, len1);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (baos != null) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void servers() {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
FileOutputStream fos = null;
OutputStream outputStream = null;
try {
serverSocket = new ServerSocket(9999);
socket = serverSocket.accept();
is = socket.getInputStream();
fos = new FileOutputStream("os2.jpg");
int len;
byte[] b = new byte[1024];
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
}
outputStream = socket.getOutputStream();
outputStream.write("照片已收到".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.UDP协议的网络编程
一、常用方法
1.public DatagramSocket(int port)创建数据报套接字并将其绑定到本地主机上的指定端口。套接字将被绑定到通配符地址,IP 地址由内核来选择。
2.public DatagramSocket(int port,InetAddress laddr)创建数据报套接字,将其绑定到指定的本地地址。本地端口必须在 0 到 65535 之间(包括两者)。如果 IP 地址为 0.0.0.0,套接字将被绑定到通配符地址,IP 地址由内核选择。
3.public void close()关闭此数据报套接字。
4.public void send(DatagramPacket p)从此套接字发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
5.public void receive(DatagramPacket p)从此套接字接收数据报包。当此方法返回时,DatagramPacket的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。 此方法在接收到数据报前一直阻塞。数据报包对象的 length 字段包含所接收信息的长度。如果信息比包的长度长,该信息将被截短。
6.public InetAddress getLocalAddress()获取套接字绑定的本地地址。
7.public int getLocalPort()返回此套接字绑定的本地主机上的端口号。
8.public InetAddress getInetAddress()返回此套接字连接的地址。如果套接字未连接,则返回 null。
9.public int getPort()返回此套接字的端口。如果套接字未连接,则返回 -1。
10.public DatagramPacket(byte[] buf,int length)构造 DatagramPacket,用来接收长度为 length 的数据包。 length 参数必须小于等于 buf.length。
11.public DatagramPacket(byte[] buf,int length,InetAddress address,int port)构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。length参数必须小于等于 buf.length。
12.public InetAddress getAddress()返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
13.public int getPort()返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
14.public byte[] getData()返回数据缓冲区。接收到的或将要发送的数据从缓冲区中的偏移量 offset 处开始,持续 length 长度。
15.public int getLength()返回将要发送或接收到的数据的长度。
二、实现过程
发送端:
1.创建DatagramSocket对象
2.创建DatagramPacket对象并设置其参数DatagramPacket(data,数据开始位置,数据结束位置,目标ip地址,使用的端口号)
3.datagramSocket.send(datagramPacket);
4.关闭DatagramSocket
接收端:
1.创建DatagramSocket对象并指定端口号(与发送端设置的端口号一致)
2.创建DatagramPacket对象并设置参数DatagramPacket(b, 0, b.length)
3.receive
4.其他操作
5.关闭DatagramSocket
三、使用
public class Test {
@org.junit.Test
public void sender() {
DatagramSocket datagramSocket = null;
try {
//DatagramSocket不用放端口号,因为我们会把数据封装到DatagramPacket中
datagramSocket = new DatagramSocket();
String data = "发送测试";
byte[] b = new byte[1024];
b = data.getBytes();
//DatagramPacket datagramPacket = new DatagramPacket(data,数据开始位置,数据结束位置,目标ip地址,使用的端口号)
DatagramPacket datagramPacket = new DatagramPacket(b, 0, b.length, InetAddress.getLocalHost(), 9090);
datagramSocket.send(datagramPacket);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (datagramSocket != null) {
datagramSocket.close();
}
}
}
@org.junit.Test
public void receiver() {
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(9090);
byte[] b = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(b, 0, b.length);
datagramSocket.receive(datagramPacket);
System.out.println(new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (datagramSocket != null) {
datagramSocket.close();
}
}
}
}
4.URL网络编程
URL:统一资源定位符,它表示 Internet 上某一 资源的地址。
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
URL对象的创建及常用方法
一、URL构造器
URL类的构造器都声明抛出非运行时异常,必须要对这一异常进行处理,通常是用 try-catch 语句进行捕获。
1.public URL (String spec):通过一个表示URL地址的字符串可以构造一个URL对象。
例如:URL url = new URL ("http://www. atguigu.com/");
2.public URL(URL context, String spec):通过基 URL 和相对 URL 构造一个 URL 对象。
例如:URL downloadUrl = new URL(url, “download.html")
3.public URL(String protocol, String host, String file);
例如:new URL("http", "www.atguigu.com", “download. html");
4.public URL(String protocol, String host, int port, String file);
例如: URL gamelan = newURL("http", "www.atguigu.com", 80, “download.html");
二、常用方法
一个URL对象生成后,其属性是不能被改变的,但可以通过它给定的方法来获取这些属性:
1.public String getProtocol()-- 获取该URL的协议名
2.public String getHost()--获取该URL的主机名
3.public String getPort()--获取该URL的端口号
4.public String getPath()--获取该URL的文件路径
5.public String getFile()--获取该URL的文件名
6.public String getQuery()--获取该URL的查询名
7.URLConnection url.openConnection()--获取服务器的连接
8.URLConnection:表示到URL所引用的远程对象的连接。当与一个URL建立连接时,首先要在一个 URL 对象上通过方法 openConnection() 生成对应的 URLConnection对象。如果连接过程失败,将产生IOException.
三、使用
URL url = new URL("http://localhost:8080/examples/myTest.txt");
System.out.println("getProtocol() :"+url.getProtocol());
System.out.println("getHost() :"+url.getHost());
System.out.println("getPort() :"+url.getPort());
System.out.println("getPath() :"+url.getPath());
System.out.println("getFile() :"+url.getFile());
System.out.println("getQuery() :"+url.getQuery());
四、从某个服务器上下载资源
过程:
1.创建URL对象并指定网址
2.url.openConnection()连接服务器
3.将2强转换为具体协议的URL连接如HttpURLConnection
4. huc.connect()连接
5.建立输入流以及输出文件流,并传数据
6.关闭流以及强壮之后的URL--HttpURLConnection
使用:
@org.junit.Test
public void URLtest() {
HttpURLConnection huc = null;
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
try {
URL url = new URL("http://www. atguigu.com/");
URLConnection urlConnection = url.openConnection();
huc = (HttpURLConnection) urlConnection;
huc.connect();
inputStream = huc.getInputStream();
fileOutputStream = new FileOutputStream("OS3.jpg");
int len;
byte[] b = new byte[1024];
while ((len = inputStream.read(b)) != -1) {
fileOutputStream.write(b, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (huc != null) {
huc.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}