java 自学日志 【十六】---网络编程
来源:互联网 发布:高中算法初步程序语言 编辑:程序博客网 时间:2024/05/16 19:48
------android培训,java培训,期待与您交流------
网络编程:
网络编程是为了实现不同主机间的数据通信,要实现通讯,则要首先知道对方的IP和端口号,同时还要明确双方使用的通信规则(传输协议)。
IP地址,端口号和传输协议就是网络通讯的三要素:
①IP地址:是主机在网络上的地址,在网上的唯一标识,127.0.0.1是本地回环地址,可测试网卡是否损坏;
②端口号:数据要发送到对方指定的应用程序上,为了标识这些应用程序,用数字对其标识,这些数字就是端 口,或被称为逻辑端口;它并无物理实体与之对应;有效端口号从0~65535,其中0~1024是系统保留的 端口号;
一些常见的端口:浏览器:80 ; tomcat服务器:8080; mysql:3306;
③传输协议:要完成传输,还要遵守相同的通信协议,国际通用协议是 TCP/IP协议,既能用于局域网,也可以 用于广域网,除了TCP/IP,还有 UDP,FTP,HTTP等协议;
网络模型:主要有两个网络模型,一是OSI模型,一是TCP/IP模型;
OSI模型:从顶到底层 分别是: 应用层,表示层,会话层,传输层,网络层,数据链路层,物理层,分七层;
TCP/IP模型:为了简化,TCP/IP将OSI的应用层,表示层,会话层合并为应用层,数据链路层和物理层合并成 主机至网络层,所以它由 应用层,传输层,网际层,主机至网络层组成;
FTP,HTTP都在应用层,TCP,UDP在传输层,IP在网际层;
数据封包:数据从应用层开始,每经一层,都加入该层的标识信息,直到物理层,这个过程叫数据封包,之后 变成二进制数据从物理设备上输出;
数据拆包:去掉每层的标识信息,获取数据的过程就是拆包过程;
网络编程现阶段主要是在网际层,传输层,而javaweb开发主要是在应用层;
java中对各个层都创建了对象与之对应,以方便我们开发使用;
IP地址:是数字,由四段组成,如192.168.1.1,使用时不便于记忆,所以有与之对应的主机名,主机名与IP地址相对应;IP常用的方法如下:都在java。net包中;
InetAddress: getLocalHost();可获取主机名和本地地址;
getHostAddress():主机地址的字符串表现形式;
getHostName():获取主机名称;
如果网络获取主机名称,可能出现解析不成功的情况,那么IP地址就是主机名,getByName("")可通过给定主机名,获取主机的IP地址;
演示:
import java.net.*;class IPDemo{public static void main(String[] args) throws Exception{InetAddress i = InetAddress.getLocalHost();System.out.println(i.toString());System.out.println("address:"+i.getHostAddress());System.out.println("name:"+i.getHostName());InetAddress [] ia = InetAddress.getAllByName("www.renren.com");for(InetAddress s : ia){System.out.println(s.toString());}//System.out.println("address:"+ia.getHostAddress());//System.out.println("name:"+ia.getHostName());}}
TCP/IP和UDP协议:两者都在传输层;
两者的区别:
①UDP:(User Datagram Protocol),用户数据报协议,是一种面向无连接的不可靠协议,它将数据源和目的封装成数据报包,在不需要建立连接的情况下就可实现传输,每个数据报包大小限制在64K内,特点是传输速度快;存在数据丢失的可能,主要应用于即时数据的传输,如QQ聊天程序,对话机,网络视频会议等;
②TCP:(Transmission Control Protocol),传输控制协议,它是面向连接的可靠的传输协议,通过三次握手的形式完成数据传输通道的连接,传输大量的数据,特点是速度相对较慢,适合对数据完整性要求高的程序,如下载应用程序;
Socket:(插座,套接字):
网络编程其实就是socket编程,它是为网络服务的一种机制,每个应用程序都有一个socket通信端点,可以把socket想象为每个应用程序的插座,通信的两端都有socket,数据在两个socket之间通过IO传输;
UDP传输:UDP两端是发送端和接受端;
DatagramSocekt:UDP传输专用的程序通信断电,既能发送也能接受;
DatagramPacket: 数据报包,封装了UDP传输的数据报包,里面可以设置发送目的地的IP地址,端口和内容;
广播地址:每个网段尾数为255的IP 地址,如192.168.1.255就是一个广播地址;
UDP代码演示:
/* 需求:通过Udp传输方式,将一段文字数据发送出去。 定义一个udp发送端。 思路: 1。建立UDPsocket服务。 2.提供数据,并将数据封装到数据包中。 3.通过socket服务的发送功能,将数据包发出去。 4.关闭资源。 */ import java.net.*;class UDPSend{public static void main(String[] args) throws Exception{ //1.创建UDP服务,通过DatagramSocket对象。DatagramSocket ds = new DatagramSocket(6666);//2.确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress address, int port)byte[] buf = "传输数据成功".getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.102"),10000);//3.通过socket服务,将已有的数据包发送出去,通过send方法。ds.send(dp);//4.关闭资源。它使用了底层的资源,所以要关闭资源。 ds.close();}}/* 需求; 定义一个应用程序,用于接收并处理数据。 定义udp接受端 思路: 1.定义socket服务,通常会监听一个端口,其实就是给这个接受网络应用程序定义一个数字标示。 方便与明确哪些数据过来该应用程序可以处理。 2.定义一个数据包,因为要存储要接受到的字节数据, 因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。 3.通过socket服务的receive方法将收到的数据存入已定义的数据包中。 4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。 5.关闭资源。 */ class UDPReceive{public static void main(String[] args) throws Exception{//1.创建udpsocket,建立端点。这里必须定义监听的端口,其实就是给网络应用程序定义数字标识。DatagramSocket ds = new DatagramSocket(10000);//2.定义数据包,用于存储数据。byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);//3.通过服务的receive方法,将收到的数据存入到数据包中。ds.receive(dp);//4.获取数据包中的方法获取其中的数据String ip = dp.getAddress().getHostAddress();String data= new String(dp.getData(),0,dp.getLength());int port = dp.getPort();System.out.println(ip+"--"+data+"--"+port);ds.close();}}UDP代码演示2:
import java.net.*;import java.io.*;//键盘录入UDP传输class UDPSend2{public static void main(String[] args) throws Exception{DatagramSocket ds = new DatagramSocket();BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));String line = null;while((line=bufr.readLine())!=null){if("886".equals(line))break;byte [] b = line.getBytes();//192.168.1.255是这个网段的广播地址,用它就能实现局域网群聊。 DatagramPacket dp = new DatagramPacket(b,b.length,InetAddress.getByName("192.168.1.255"),10001);ds.send(dp);}ds.close();}}class UDPRece2{public static void main(String[] args) throws Exception{DatagramSocket ds = new DatagramSocket(10001);while(true){byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);ds.receive(dp);String ip =dp.getAddress().getHostAddress();String data = new String(dp.getData(),0,dp.getLength());System.out.println(ip+"说:"+data);}}}
利用UDP,编写一个聊天程序
有接受数据的部分,和发数据的部分。
这两部分需要同时执行。那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法,
而且run方法要封装到不同的类中。
import java.net.*;import java.io.*;class Send implements Runnable{private DatagramSocket ds;//public Send(DatagramSocket ds){this.ds = ds;}public void run(){try{BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));String line = null;while((line = bufr.readLine())!=null){if("886".equals(line))break;byte[] buf =line.getBytes();//把发送地址,设为广播地址,InetAddress i = InetAddress.getByName("192.168.1.255");DatagramPacket dp=new DatagramPacket(buf,0,buf.length,i,10020);ds.send(dp);}ds.close();}catch (Exception e){throw new RuntimeException("发送端失败");}}}class Rece implements Runnable{private DatagramSocket ds;public Rece(DatagramSocket ds){this.ds = ds;}public void run(){try{while(true){byte [] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);ds.receive(dp);String ip = dp.getAddress().getHostAddress();String data = new String(dp.getData(),0,dp.getLength());System.out.println("ip:"+ip+" data:"+data);}}catch (Exception e){throw new RuntimeException("接受端失败");}}}class ChatDemo{public static void main(String[] args) throws Exception{DatagramSocket sendSoket = new DatagramSocket();DatagramSocket receSoket = new DatagramSocket(10020);new Thread(new Send(sendSoket)).start();new Thread(new Rece(receSoket)).start();}}
TCP传输:对应的是客户端和服务端
Socket:TCP传输客户端通信端点;
ServerSocket: TCP传输服务端端点;serversocket(port,backlog)这个构造函数中的backlog用于指定客户端的最大连接数;
因为TCP需要建立连接,所以socket客户端一建立就要指定服务端的IP和端口,而在服务端建立时,要设置监听的端口,TCP连接成功后,在客户端和服务端就会产生网络流,客户端提供对网络流进行读写的输入流和输出流对象,服务端操作网络流时,先获取客户端的socket对象,然后利用该socket的字节输入输出流进行读写操作,客户端和服务端进行多次交互时,注意阻塞式方法对程序的影响;
TCP代码演示一:
TCP代码演示一:
演示TCP传输。
1.tcp分客户端和服务端。
2.客户端对应的对象是Socket。
服务端对应的对象是SeverSocket
1.tcp分客户端和服务端。
2.客户端对应的对象是Socket。
服务端对应的对象是SeverSocket
/* 客户端: 通过查阅Socket对象,发现在该对象建立时,就可以连接指定的主机。 因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在, 并连接成功,形成通路后,在该通道进行数据的传输。 需求:给服务段发送一个文本数据。 步骤: 1.创建Socket服务,并指定要连接的主机和端口。 2.为了发送数据,应该获取Socket流中的输出流。 3.获取输出流后写入数据。 4.socket关闭客户端Socket服务,也就关闭了网络流资源。*/ import java.net.*;import java.io.*;class TCPClient{public static void main(String[] args) throws Exception{Socket s = new Socket("192.168.1.102",10086);OutputStream out = s.getOutputStream();out.write("i am coming!".getBytes());s.close();}}/* 难在服务端上。 需求:定义端点,接受数据,并打印在控制台上。 服务端: 1.建立服务端的Socket服务,通过SeverSocket();并监听一个端口。 2. 获取连接过了的客户端对象。 通过SeverSocket的accept方法。没有就会等,所以这个方法是阻塞式的。 3.客户端如果发过了数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过了的数据。并打印在控制台上。 4.关闭服务。(可选操作,服务端一般是一直开着的)。 */ class TCPServer{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10086);Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"......connect");InputStream in = s.getInputStream();byte[] buf = new byte[1024];int len = in.read(buf);System.out.println(new String(buf,0,len));s.close();}}
演示代码二:
演示tcp的传输的的客户端和服务端的互访。
需求:客户端给服务端发送数据,服务端收到数据后,给客户端反馈信息。
需求:客户端给服务端发送数据,服务端收到数据后,给客户端反馈信息。
/* 客户端: 1.建立socket服务,指定要连接的主机和端口 1.获取Socket流中的输出流,将数据写入到该流中,通过网络发送给服务端。 3.获取socket流中的输入流,将服务端反馈的数据获取到,并打印, 4.关闭客户端资源。 */ import java.io.*;import java.net.*;class TCPC2{public static void main(String[] args) throws Exception{Socket s = new Socket("192.168.1.102",10010);OutputStream out = s.getOutputStream();out.write("收到了吗?".getBytes());InputStream in = s.getInputStream();byte[] buf = new byte[1024];int len = in.read(buf);System.out.println(new String(buf,0,len));s.close();}}class TCPS2{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10010);Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"....connect");InputStream in = s.getInputStream();byte[] buf = new byte[1024];int len = in.read(buf);System.out.println(new String(buf,0,len));OutputStream out = s.getOutputStream();out.write("收到了".getBytes());s.close();}}
演示代码三:
需求:建立一个文本转换服务器。
客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端。
而且,客户端可以不断的进行文本转换。当客户端输入over,转换就结束。
分析:
客户端:
既然是操作设备上的数据,那么就可以使用io技术,并按照IO的操作规律来思考。
源:键盘录入
目的:网络设备,也就是网络输出流,
而且操作的是文本数据,可以选择字符流。
步骤:
1,建立服务
2.获取键盘录入
3,将数据发给服务端。
4.获取服务端返回的大写数据。
5.结束,关闭资源。
都是文本数据,可以使用字符流进行操作。同时提高效率,要加入缓冲。
客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端。
而且,客户端可以不断的进行文本转换。当客户端输入over,转换就结束。
分析:
客户端:
既然是操作设备上的数据,那么就可以使用io技术,并按照IO的操作规律来思考。
源:键盘录入
目的:网络设备,也就是网络输出流,
而且操作的是文本数据,可以选择字符流。
步骤:
1,建立服务
2.获取键盘录入
3,将数据发给服务端。
4.获取服务端返回的大写数据。
5.结束,关闭资源。
都是文本数据,可以使用字符流进行操作。同时提高效率,要加入缓冲。
import java.io.*;import java.net.*;class TCPC3{public static void main(String[] args) throws Exception{Socket s = new Socket("192.168.1.102",10088);//定义读取键盘数据的流对象BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//定义目的,将数据写入socket输出流,发给服务器BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); //PrintWriter out = new PrintWriter(s.getOutputStream(),true); //定义一个socket读取流,读取服务端返回的信息。 BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));String line = null;while((line=bufr.readLine())!=null){if("over".equals(line))break;bufout.write(line);bufout.newLine();bufout.flush();//out.println(line);String str = bufin.readLine();System.out.println("Server:"+str);}bufr.close();s.close();}}class TCPS3{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10088); Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.println(ip+".....connect"); //读取socket读取流中的数据BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));//目的,socket输出流,将大写数据写入到socket输出流,并发送给客户端。 BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); //PrintWriter out = new PrintWriter(s.getOutputStream(),true); String line = null;while ((line=bufin.readLine())!=null){System.out.println(line);bufout.write(line.toUpperCase());bufout.newLine();bufout.flush();//out.println(line.toUppCase());}s.close();ss.close();}}代码演示四:
TCP上传文件(使用IO字符流)
把文件从客户端传到服务器端上。
容易出现的问题:没有客户端上传完后,文件结束标记,服务器无法停止连接Socket连接。
import java.io.*;import java.net.*;class TCPC4{public static void main(String[] args) throws Exception{Socket s = new Socket("192.168.1.102",11000);BufferedReader bufr = new BufferedReader(new FileReader("IPDemo.java"));PrintWriter out = new PrintWriter(s.getOutputStream(),true);String line= null;while ((line=bufr.readLine())!=null){out.println(line);}s.shutdownOutput();BufferedReader bufin= new BufferedReader(new InputStreamReader(s.getInputStream()));String str = bufin.readLine();System.out.println(str);bufr.close();s.close();}}class TCPS4{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(11000);Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"....connect");BufferedReader bufin = new BufferedReader(new InputStreamReader(s.getInputStream()));PrintWriter out = new PrintWriter(new FileWriter("copy.txt"),true);String line = null;while ((line=bufin.readLine())!=null){out.println(line);}PrintWriter pw = new PrintWriter(s.getOutputStream(),true);pw.println("上传成功!");out.close();s.close();ss.close();}}
TCP传输的两个问题:
①客户端与服务端交互时同时阻塞,当客户端和服务端有多个阻塞方法时,如果使用缓冲区读取每行,没有刷新和换行,会导致同时阻塞;
②定义结束标记:定义结束标记的方法:定义“over“这样的字符标记,或者盖时间标记,或者使用socket的shutdownOutput和shutdownInput方法(建议使用)。
代码演示五:
需求:上传图片
客户端:
1.服务端点
2.读取客户端已有的图片数据
3.通过socket的输出流将数据发给服务端。
4.读取服务端反馈信息。
5.关闭。
客户端:
1.服务端点
2.读取客户端已有的图片数据
3.通过socket的输出流将数据发给服务端。
4.读取服务端反馈信息。
5.关闭。
import java.net.*;import java.io.*;class PICC{public static void main(String[] args) throws Exception{Socket s =new Socket("192.168.1.102",10090);FileInputStream fis = new FileInputStream("L.jpg");OutputStream out = s.getOutputStream();byte[] buf = new byte[1024];int len = 0;while((len=fis.read(buf))!=-1){out.write(buf,0,len);}s.shutdownOutput();InputStream fin= s.getInputStream();byte[] bufin = new byte[1024];int in = fin.read(bufin);System.out.println(new String(bufin,0,in));fis.close();s.close();}}class PICS{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10090);Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"....connected");InputStream in = s.getInputStream();FileOutputStream fout = new FileOutputStream("copy.jpg");byte[] buf = new byte[1024];int len= 0;while((len=in.read(buf))!=-1){fout.write(buf,0,len);}OutputStream out= s.getOutputStream();out.write("上传成功".getBytes());fout.close();s.close();ss.close();}}
TCP客户端并发访问:客户端并发访问服务器时,把服务端的处理代码封装在Runnable实现子类的run方法中,并把服务器获得的socket对象传递给该实现子类的构造函数,服务端通过while循环启动多个线程,对每个客户端请求进行并发处理,这也是一个服务器的基本原理;
import java.net.*;import java.io.*;class PICC1{public static void main(String[] args) throws Exception{if (args.length!=1){System.out.println("请选择要上传的图片");return ;}File file= new File(args[0]);if(!(file.exists()&&file.isFile())){System.out.println("图片不存在或不是图片文件");return ;}if(!file.getName().endsWith(".jpg")){System.out.println("图片格式错误,请选择jpg格式图片");return ;}if (file.length()>1024*1024*3){System.out.println("文件过大,上传失败");return ;}Socket s =new Socket("192.168.1.102",10090);FileInputStream fis = new FileInputStream(file);OutputStream out = s.getOutputStream();byte[] buf = new byte[1024];int len = 0;while((len=fis.read(buf))!=-1){out.write(buf,0,len);}s.shutdownOutput();InputStream fin= s.getInputStream();byte[] bufin = new byte[1024];int in = fin.read(bufin);System.out.println(new String(bufin,0,in));fis.close();s.close();}}/* 服务端: 这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程。 这时B客户端连接,只有等待。因为服务端还没有处理完A客户端的请求。还没有循环回来 执行下次accept方法。所以,暂时获取不到B客户端对象。那么为了可以让多个客户端 同时并发访问服务端。那么服务端最好就是将每个客户端封装到一个单独的线程中去。这 样就可以同时处理多个客户端请求。如何定义线程?只要明确了每一个客户端要在服务端 执行的代码即可。将该代码存入run方法中。 */ class PICThread implements Runnable{private Socket s;PICThread(Socket s){this.s= s;}public void run(){String ip = s.getInetAddress().getHostAddress();int c = 0;try{System.out.println(ip+"...已连接");InputStream in = s.getInputStream();File file= new File(ip+".jpg");while(file.exists())file= new File(ip+"("+(c++)+")"+".jpg");FileOutputStream fout = new FileOutputStream(file);byte[] buf = new byte[1024];int len= 0;while((len=in.read(buf))!=-1){fout.write(buf,0,len);}OutputStream out= s.getOutputStream();out.write("上传成功".getBytes());fout.close();s.close();}catch (Exception e){throw new RuntimeException(ip+"上传失败");}}}class PICS1{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10090);while(true){Socket s = ss.accept();new Thread(new PICThread(s)).start();}}}练习:
客户端通过键盘录入用户名:
服务端对这个用户名进行校验。
如果该用户存在,在服务器端显示***,已登录。
并在客户端显示:***,欢迎光临。
如果该用户不存在,在服务器端显示 ***,尝试登陆
并在客户端显示 ***,该用户不存在。
最多就登陆三次。
服务端对这个用户名进行校验。
如果该用户存在,在服务器端显示***,已登录。
并在客户端显示:***,欢迎光临。
如果该用户不存在,在服务器端显示 ***,尝试登陆
并在客户端显示 ***,该用户不存在。
最多就登陆三次。
import java.io.*; import java.net.*;class LOGINC{public static void main(String[] args) throws Exception {Socket s = new Socket("192.168.1.102",11000);BufferedReader bfr= new BufferedReader(new InputStreamReader(System.in));PrintWriter out = new PrintWriter(s.getOutputStream(),true);BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));for(int x= 0;x<3;x++){String line= bfr.readLine();if(line==null)break;out.println(line);String info = in.readLine();System.out.println("info:"+info);if(info.contains("欢迎"))break;}bfr.close();s.close();}}class LOGINT implements Runnable{private Socket s;LOGINT(Socket s){this.s= s;}public void run(){String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"......已连接");try{for (int x=0;x<3 ;x++ ){BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));String name = in.readLine();if (name==null)break;BufferedReader bufr =new BufferedReader(new FileReader("log.txt")); PrintWriter out = new PrintWriter(s.getOutputStream(),true); boolean flag = false;String line=null;while((line=bufr.readLine())!=null){if(line.equals(name)){flag = true;break;}}if(flag){System.out.println(name+"已登录");out.println(name+"欢迎光临");break;}else{System.out.println(name+"...尝试登陆");out.println(name+"..用户名不存在");}}s.close();}catch (Exception e){throw new RuntimeException(ip+"...登陆失败");}}}class LOGINS{public static void main(String[] args) throws Exception {ServerSocket ss = new ServerSocket(11000);while (true){Socket s = ss.accept();new Thread(new LOGINT(s)).start();}}}
URL:代表一个统一资源定位符,是指向互联网资源的指针,资源可以是简单的文本或目录,也可以是更为复杂对象的引用,如对数据库或搜索引擎的查询;
常用方法:
①int getDefaultPort(): 获取与此URL关联协议的默认端口;
②String getFile(): 获取此URL的文件名;
③String getHost(): 获取此URL的主机名;
④String getPath():或取此URL的路径;
⑤int getPort(): 获取此URL的端口号;
⑥ String getProtocol(): 获取此URL的协议名称;
⑦String getQuery(): 获取此URL的查询部分;
代码演示:
import java.net.*; class URLDemo { public static void main(String[] args) throws Exception { //URL url=new URL("http://192.168.1.13:11000/myweb/demo.html"); URL url=new URL("http://192.168.1.13:11000/myweb/demo.html?name=haha&age=30"); System.out.println("getProtocol():"+url.getProtocol()); //http System.out.println("getHost():"+url.getHost());//192.168.1.13 System.out.println("getDefaultPort():"+url.getDefaultPort());//80,如果关联的协议没有默认的端口,则值为-1; System.out.println("getPort():"+url.getPort()); // 11000,如果没有设置则为-1; System.out.println("getPath():"+url.getPath());// /myweb/demo.html System.out.println("getFile():"+url.getFile());///myweb/demo.html?name=haha&age=30 System.out.println("getQuery():"+url.getQuery());//name=haha&age=30 /* int port = url.getPort(); if(port==-1) port =80; getPort() = -1 */ } }URLConnection:作用类似于socket,其实内部封装了socket,所以可以获取网络输入输出流,通过URL和URLConnection可以方便的对应用层网络数据进行读取和操作;
代码演示:
import java.net.*; import java.io.*; class URLConnectionDemo { public static void main(String[] args) throws Exception { URL url=new URL("http://192.168.1.13:8080/myweb/demo.html"); URLConnection conn = url.openConnection(); System.out.println(conn+"-------"); InputStream in = conn.getInputStream(); byte [] buf =new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); } }
自定义图形化界面浏览器
import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; class MyIEByGUI { private Frame f; private TextField tf; private Button but; private TextArea ta; private Dialog d; private Label lab; private Button okBut; MyIEByGUI() { init(); } public void init() { f = new Frame("My IE"); f.setBounds(300,100,500,400); f.setLayout(new FlowLayout()); tf = new TextField(40); but = new Button("转到"); ta = new TextArea(20,50); d = new Dialog(f,"提示信息-self",true); d.setBounds(400,200,240,200); d.setLayout(new FlowLayout()); lab =new Label(); okBut=new Button("确定"); d.add(lab); d.add(okBut); f.add(tf); f.add(but); f.add(ta); myEvent(); f.setVisible(true); } public void myEvent() { but.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { showWebPage(); } catch (Exception ex) { } } }); tf.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e)//用keyTyped事件不成功 { if(e.getKeyCode()==KeyEvent.VK_ENTER) { try { showWebPage(); } catch (Exception ex) { } } } }); okBut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { d.setVisible(false); } }); d.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { d.setVisible(false); } }); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } private void showWebPage() throws Exception { ta.setText(""); //http://192.168.1.13:8080/myweb/demo.html String url =tf.getText(); int index1 = url.indexOf("//")+2; int index2 = url.indexOf("/",index1); String str =url.substring(index1,index2); String[] arr = str.split(":"); String host = arr[0]; int port = Integer.parseInt(arr[1]); String dir = url.substring(index2); //ta.setText(url); ta.setText(port+","+null); //建立Socket客户端 Socket s = new Socket(host,port); //发送请求消息头 PrintWriter out = new PrintWriter(s.getOutputStream(),true);//别忘了加true out.println("GET "+dir+" HTTP/1.1"); out.println("Accept: */*"); out.println("Accept-Language: zh-cn"); out.println("Host: 192.168.1.13:11000"); out.println("Connection: Keep-Closed"); out.println();//记得一定要加空行 out.println(); BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream())); String line = null; while((line=bufr.readLine())!=null) { ta.append(line+"\r\n"); } s.close(); } public static void main(String[] args) { new MyIEByGUI(); } } private void showWebPage() throws Exception { //使用URL和URLConnection对showWebPage改写。 //很明显,这两个封装的应用层对象使用起来更方便简洁 ta.setText(""); String urlPath =tf.getText(); URL url=new URL(urlPath); URLConnection conn = url.openConnection(); //System.out.println(conn); InputStream in = conn.getInputStream(); byte [] buf =new byte[1024]; int len = in.read(buf); ta.setText(new String(buf,0,len)); }
域名解析:用IP地址登陆网站,数字不好记忆,习惯用主机名,如www.baidu.com,从主机名到获得该主机名对应的IP地址的过程,就是域名解析,它一般是DNS服务器完成的;
域名解析步骤大致分为2步:
①查找本地的IP地址和主机名映射表,如果存在映射,则使用本机映射,如:127.0.0.1和localhost的对应关系就在这个映射表中,通过对映射文件进行配置可以实现一些功能,如:将常用网站配置在表中,这样速度快些,还可以屏蔽过滤一些垃圾网站;
②如果第一步没有找到,就会去设置的DNS服务器查找,找到对应的IP地址,获取地址后,再返回给本机IP地址,本机再通过IP地址链接上想要访问的网站。
- java 自学日志 【十六】---网络编程
- 黑马程序员 Java自学总结十六 网络编程
- Java基础知识 十六 (网络编程)
- java自学笔记之网络编程
- java自学日记6(网络编程)
- Java 自学日志【一】
- Java 自学日志【二】
- java网络编程自学(三)-TCP/IP+NIO
- 黑马程序员java自学总结之--网络编程
- java自学笔记————网络编程
- 嵌入式网络编程-自学篇
- java 自学日志【四】---数组
- java 自学日志【八】---异常
- java 自学日志【九】---多线程
- java 自学日志【十五】---GUI
- unix网络编程-十五,十六章-小结
- UNIX网络编程----线程(二十六)
- 黑马程序员《java基础总结(十六)》(网络编程<反射、正则表达式>)
- 64位Windows操作系统部署ASP.NET Web应用常见问题
- 在50行代码贪吃蛇 笔记
- 构造函数不能声明为虚函数的原因是:
- 一个软件工程师的职业规划
- 黑马程序员_类加载器
- java 自学日志 【十六】---网络编程
- PHP扩展开发与内核应用阅读笔记---php的内存管理
- 关于winrar4.20注册码问题
- 黑马程序员_网络编程
- 你是狗吗?
- 黑马程序员_线程
- java.net.ConnectException: localhost/127.0.0.1:8080 - Connection refused
- JUnit的jar包和hamcrest的jar包关系
- 黑马程序员_异常