网络编程
在网络间完成数据的传输,io流在本地完成数据的传输
网络编程2要素
- 如何准确地定位网络上一台或多台主机【ip】
- 找到主机后如何可靠高效地进行数据传输。【协议】
通信规则
- OSI参考模型:模型过于理想化
- TCP/IP参考模型(或TCP/IP协议):事实上的国际标准
?
端口号
端口号标识正在计算机上运行的进程, 被规定为一个 16 位的整数 0~65535。
其中,0~1023被预先定义的服务通信占用(如MySql占用端口3306,http占用端口80等)。除非我们需要访问这些特定服务,否则,就应该使用 1024~65535 这些端口中的某一个进行通信,以免发生端口冲突。?
InetAddress ?java.net?
唯一标识 Internet 上的计算机,InetAddress类主要表示IP地址,有两个子类:Inet4Address、Inet6Address。
主机有两种方式表示地址 IP和域名。 域名解析:先找本机hosts,是否有输入的域名地址,没有的话,再通过DNS服务器,找主机。 在hosts文件 ?C:\Windows\System32\drivers\etc ip地址:127.0.0.1 ?本地域名:localhost?
@Test
public void test01() throws Exception {
InetAddress byName = InetAddress.getByName("www.baidu.com");
//获取InetAddress实例域名
System.out.println(byName.getHostName());
//获取InetAddress实例ip地址
System.out.println(byName.getHostAddress());
System.out.println("------------------");
InetAddress localHost = InetAddress.getLocalHost();
//获取本地主机域名
System.out.println(localHost.getHostName());
//获取本地主机ip地址
System.out.println(localHost.getHostAddress());
}
TCP协议:【客户端和服务端】
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用“三次握手”方式,是可靠的
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
- 优点:可靠,安全,但是效率低。【每一次发送数据都要服务端确认】
UDP协议:【发送端和接收端】
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内
- 因无需连接,故是不可靠的
- 发送数据结束时无需释放资源,速度快
套接字Socket?
端口号与IP地址的组合得出一个网络套接字。
- 通信的两端都要有Socket,是两台机器间通信的端点,网络通信其实就是Socket间的通信。
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
- 客户端和服务器现在可以通过对
Socket 对象的写入和读取来进行进行通信。
?ctrl+alt+T[try...catch],快速生成try...catch结构
Socket accept() throws IOException ?? ? 等待客户端的连接请求,返回与该客户端进行通信用的Socket对象
void close()throws IOException?? ? 关闭监听Socket
打开连接到 Socket 的输入/出流 InputStream getInputStream() ?throws IOException 获取与Socket相关联的字节输入流,用于从Socket中读数据。
OutputStream getOutputStream() ?throws IOException 获取与Socket相关联的字节输出流,用于向Socket中写数据。
Socket java.net.Socket? 和 ServerSocket?java.net.ServerSocket
客户端要获取一个Socket 对象通过实例化 ,而 服务器获得一个Socket 对象则通过accept() 方法的返回值
//客户端
@Test
public void client() throws Exception {
String str = "我在精神病院斩神";
//当Socket构造方法返回,并没有简单的实例化了一个Socket对象,
//它实际上会尝试连接到指定的服务器和端口
Socket s = new Socket(InetAddress.getByName("localhost"), 9898);
//发送数据给服务端
OutputStream os = s.getOutputStream();
os.write(str.getBytes());
//发送完毕
s.shutdownOutput();
//接收服务端的反馈
InputStream in = s.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while((len = in.read(b)) != -1){
System.out.println(new String(b, 0, len));
}
in.close();
os.close();
s.close();
}
//服务端
@Test
public void server() throws IOException {
//应用程序已经绑定到指定的端口,并且侦听客户端请求
ServerSocket ss = new ServerSocket(9898);
//该accept()方法将一直等待,直到客户端连接到服务器上给定的端口。
Socket s = ss.accept();
//接收客户端数据
InputStream in = s.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while((len = in.read(b)) != -1){
System.out.println(new String(b, 0, len));
}
//发送反馈给客户端
OutputStream os = s.getOutputStream();
os.write("成功接收数据".getBytes());
os.close();
in.close();
s.close();
ss.close();
}
从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。并关闭相应的连接
//3.从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。并关闭相应的连接
public class FileTest {
//客户端
@Test
public void client() throws IOException {
Socket s = new Socket(InetAddress.getByName("192.168.15.86"), 9898);
OutputStream os = s.getOutputStream();
FileInputStream fis = new FileInputStream("./1.jpg");
byte[] b = new byte[1024];
int len = 0;
while ((len = fis.read(b)) != -1) {
os.write(b, 0, len);
}
//发送完毕
s.shutdownOutput();
//接收反馈
InputStream in = s.getInputStream();
while ((len = in.read(b)) != -1) {
System.out.println(new String(b, 0, len));
}
in.close();
fis.close();
os.close();
s.close();
}
//服务端
@Test
public void server() throws IOException {
ServerSocket ss = new ServerSocket(9898);
//处于阻塞,等待连接的那个Socket
Socket s = ss.accept();
//使用输出流FileOutputStream把图片保存到本地
InputStream in = s.getInputStream();
FileOutputStream fos = new FileOutputStream("./2.jpg");
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) != -1) {
fos.write(b, 0, len);
}
//给客户端返回信息
OutputStream os = s.getOutputStream();
os.write("接收图片成功".getBytes());
os.close();
fos.close();
in.close();
s.close();
ss.close();
}
}
DatagramSocket与DatagramPacket ?java.net.DatagramPacket 系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
public class FileTest {
//UDP发送端
@Test
public void client() throws IOException {
//使用UDP协议传输
DatagramSocket datagramSocket = new DatagramSocket();
byte[] bytes="我在精神病院学斩神".getBytes(StandardCharsets.UTF_8);
//DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
//构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
DatagramPacket p=new DatagramPacket(bytes,0,bytes.length, InetAddress.getByName("127.0.0.1"),9898);
datagramSocket.send(p);
datagramSocket.close();
}
//UDP接收端
@Test
public void server() throws IOException {
//使用UDP协议传输
DatagramSocket datagramSocket = new DatagramSocket(9898);
byte[] bytes=new byte[1024];
//DatagramPacket(byte[] buf, int length)
//构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket p=new DatagramPacket(bytes,bytes.length);
datagramSocket.receive(p);
System.out.println(new String(p.getData(),0,p.getData().length));
datagramSocket.close();
}
}
java.net.URL
URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一资源的地址。
?URL的基本结构由5部分组成: <传输协议>://<主机名>:<端口号>/<文件名> 例如: http://192.168.1.100:8080/helloworld/index.jsp
构造器: URL(String spec)? ? ? ? ? ? 根据 String 表示形式创建 URL 对象。 方法: public final InputStream openStream() throws IOException 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。
此方法是下面方法的缩写: openConnection().getInputStream()
public URLConnection openConnection() throws IOException 返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
//获取整个url结构 一个URL对象生成后,其属性是不能被改变的,但可以通过它给定的方法来获取这些属性
public String getProtocol( ?) ?;//URL的协议名
public String getHost( ?) ?;//该URL的主机名
public String getPort( ?) ;// 获取该URL的端口号
public String getPath( ?) ? ? ? ? ? 获取该URL的文件路径
public String getFile( ?) ? ? ? ? ? ? 获取该URL的文件名
public String getRef( ?) ? ? ? ? ? ? 获取该URL在文件中的相对位置
public String getQuery( ? ) ? ? ? ?获取该URL的查询名
@Test
public void test03() throws Exception {
// 通过一个表示URL地址的字符串可以构造一个URL对象
URL url = new URL("http://192.168.15.55/atguigu/hello.txt");
// InputStream in = url.openStream(); //openStream():能从网络上读取数据,获取指定站点的资源
URLConnection connection = url.openConnection(); //不仅可以获取指定站点资源,还可以发送资源到指定站点
InputStream in = connection.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while((len = in.read(b)) != -1){
System.out.println(new String(b, 0, len));
}
in.close();
}
|