黑马程序员_Java基础-网络编程
来源:互联网 发布:stringbuffer转成数组 编辑:程序博客网 时间:2024/05/21 06:46
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1.网络参考模型
1.1 OSI模型:数据从应用层一直封装到物理层然后发送出去。再从物理层接收进来一直解封数据到应用层显示数据。这就是一个数据传递的过程。
1.2 TCP/IP参考模型:跟OSI模型的传输差不多。就是少了三层。更加的简单,容易使用。
2.网络通讯要素
2.1 IP地址(InetAddress)
①网络中设备的标识
②不容易记忆,可用主机名
③本地回环地址:127.0.0.1 主机名:localhost
2.2 端口号
①用于标识进程的逻辑地址,不同进程的标识
②有效端口0~65535,其中的0~1024为系统使用或系统保留端口,一般不建议使用
2.3 传输协议
①即是通讯的规则
②常见协议:TCP,UDP
3.TCP和UDP
3.1 TCP协议
①建立连接,形成传输数据的通路
②在连接中传输大量数据
③必须建立连接,效率会稍微低点,是可靠协议
④通过三次握手完成连接
(1)第一次 客户端向服务器发送一条确认服务器在不在的消息,进入SYN_SEND状态,等待服务器确认 “HI,在不 在不”
(2)第二次 服务器如果在的话,接收后就发回一条消息给客户端,证明它在。服务器进入SYN_RECV状态 “我在”
(3)第三次 客户端接收到服务器发回它在的消息后,为了确认客户端接收到这条消息,客户端又发送一条它接收到的消息给服务器,消息发送完毕,服务器和客户端都进入ESTABLISHED状态,即是准备发送消息状态 “我收到你的消息啦!我准备发送数据咯”
3.2 UDP协议
①将数据和目的源封装在数据包中,无需建立连接,单向传输
②每个数据包的大小限制不能超过64K
③因为没建立连接,是不可靠协议
④又因为没有连接,所以传输速度快
4.Socket(套接字、插座)
①Socket是网络通信之间的一种机制,可以用来实现不同计算机和虚拟机之间的通信
②通信的两端都有Socket
③网络通信就是Socket之间的通信
④数据在两个Socket之间通过IO流进行传输
5.UDP传输(主要操作类DatagramSocket和DatagramPacket)
5.1 UDP发送端
①建立UDPScoket服务,即是DatagramSocket
②提供数据,封装进DatagramPacket
③通过DatagramSocket的send方法发送数据包
④关闭资源
5.2 UDP服务器端
①定义UDPScoket服务。并需要监听一个端口号,如果不指定则系统会自动分配,一般自己指定,因为不知道系统会分配个什么端口号,而且也方便管理和发送端发送数据。
②定义一个DatagramPacket用于接收发送端发送过来的数据包
③用DatagramSocket的receive方法
④调用DatagramPacket的方法获取需要的数据
⑤关闭资源(可选操作),一般服务器都需要一直开着。
5.3 例子
5.3.1 例子描述:客户端键盘录入向服务器发送文本数据,服务器接收到打印到控制台,客户端输入886则结束通讯;
5.3.2 代码解释
①客户端代码:
import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class UDPClient {public static void main(String[] args) throws Exception{//第一步 创建UDPScoket服务,指定发送端口,不指定让系统随机分配也行。因为下面的数据包那里才是指定服务器的端口。这里的端口没什么实际意义DatagramSocket ds=new DatagramSocket(8888);//第二步 确定数据BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));//获取键盘的输入流String line=null;while((line=bufr.readLine())!=null){//读取键盘输入的数据byte[] buf=line.getBytes();//定义一个byte数组储存键盘录入的数据DatagramPacket dp=new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.31.58"), 10001);//定义数据包并封装数据 各参数对应意思:byte数组数据,数据长度,服务器IP地址或主机名,服务器指定的端口号//第三步 发送数据ds.send(dp);if("886".equals(line))//如果输入886则不再录入键盘数据break;}//第四步 关闭资源ds.close();}}
②服务器端代码:
import java.net.DatagramPacket;import java.net.DatagramSocket;public class UDPServer {public static void main(String[] args) throws Exception{//第一步 定义UDPScoket服务 监听10001端口DatagramSocket ds=new DatagramSocket(10001);//第二步 定义一个数据包,存储数据byte[] buf=new byte[1024];DatagramPacket dp=new DatagramPacket(buf, buf.length);//因为不是接收一次就结束,所以用循环不断接收数据。while(true){//第三步 接收数据ds.receive(dp);//处理并输出数据String data=new String(dp.getData(),0,dp.getLength());//获取文本数据String ip=dp.getAddress().getHostAddress();//获取IP地址String port=dp.getPort()+"";//获取客户端的端口号System.out.println(ip+":"+port+"-"+data);if("886".equals(data)){break;}}}}
6.TCP传输(主要操作类Socket和ServerSocket)
服务器和客户端操作同一个socket,客户端和服务器端3次握手建立连接后,服务器端会产生一个socket实例。跟客户端的一样。用该socket中的输入流和输出流进行数据之间的传输。这样也解决了多客户端访问时的数据传输错乱问题。
6.1 TCP客户端
①创建Scoket服务 指定服务端的主机名和端口号
②获取Scoket里面的输出流,用以向服务端发送数据
③关闭服务
6.2 TCP服务器端
①定义ServerScoket服务并监听一个端口,不监听则系统自动分配
②根据需求获取scoket里面对应输入输出流,接收客户端数据或向客户端发送数据
③关闭服务(可选操作)一般服务器不关闭
6.3 例子一
6.3.1例子描述:
客户端:向服务器上传文件,并接收服务器返回的数据
服务端:接收客户端上传的文件,保存并返回上传成功数据
6.3.2 代码解释
①客户端
import java.io.BufferedReader;import java.io.FileReader;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class TCPClient {public static void main(String[] args) throws Exception{//第一步 创建Socket服务 指定服务器主机和端口号Socket s=new Socket("192.168.31.58",10006);BufferedReader bufr=new BufferedReader(new FileReader("D:\\server.txt"));//创建一个文件流,上传文件//第二步 获取Socket中的输出流,用以发送数据PrintWriter writer=new PrintWriter(s.getOutputStream(),true);//用PrintWriter类可以自动帮我们完成flush动作,输出数据String line=null;//定义一个字符串存储数据while((line=bufr.readLine())!=null){//不断读取文件流中数据writer.println(line);//把读取到的数据发送到服务器}s.shutdownOutput();//标识一个文件上传结束的标记。不然服务器端不知道文件上传完成会一直接收。造成阻塞从而执行不了后面的代码。BufferedReader reader=new BufferedReader(new InputStreamReader(s.getInputStream()));//接收服务器返回的数据String callbackStr=reader.readLine();//读取服务器返回的数据System.out.println(callbackStr);//输出服务器返回的数据bufr.close();//关闭文件流//第三步 关闭socket服务,不正常关闭的话,会报异常。没有执行close程序就关闭则是不正常关闭。服务器端会报异常。不过并不影响。建议完成通讯或者数据传输则关闭s.close();}}
②服务器端
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class TCPServer {public static void main(String[] args) throws Exception{//第一步 定义ServerSocket服务,并监听10006端口,不监听则系统分配。一般需要监听。ServerSocket ss=new ServerSocket(10006);//第二步 调用accept方法接收数据,调用该方法会阻塞,直到接收到客户端请求,接收到后会返回一个socket对象。Socket s=ss.accept();//第三步 根据需求获取客户端socket里面的输入流和输出流来进行对应操作BufferedReader reader=new BufferedReader(new InputStreamReader(s.getInputStream()));//获取socket里面的输入流读取数据PrintWriter writer=new PrintWriter(new FileWriter("D:\\server-copy.txt"),true);//定义一个保存客户端上传文件的输出流。String line=null;while((line=reader.readLine())!=null){//读取客户端发来的数据writer.println(line);//把读取到的数据写入文件中。}BufferedWriter bufr=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//获取socket里面的输出流,输出上传成功给客户端bufr.write("上传成功!");//反馈数据给客户端bufr.flush();writer.close();//关闭文件流s.close();ss.close();}}
6.4 例子二
6.4.1 例子描述:
并发登录。可以多个用户同时登录。用户名储存在一个user.txt文件中。查询时查找该文件即可。文件数据排版为一行一个用户名。键盘录入用户名。提交服务器验证,返回验证结果。此例子只校验用户名。正确则登录。失败3次则断开连接。
6.4.2 运行结果图
左边服务器端,右边客户端
6.4.3 代码解释
①客户端
import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.Socket;public class LoginClient {public static void main(String[] args) throws Exception{//定义Socket服务,传入服务器的IP和对应端口号Socket s=new Socket("127.0.0.1",10011);//获取键盘录入流BufferedReader bufIn=new BufferedReader(new InputStreamReader(System.in));//获取socket的输出流向服务器输出数据用以登陆PrintWriter writer=new PrintWriter(s.getOutputStream(),true);//BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//获取socket的输入流获取服务器反馈的数据BufferedReader reader=new BufferedReader(new InputStreamReader(s.getInputStream()));//定义只能错误三次for(int i=0;i<3;i++){String name=null;//获取键盘录入的用户名name=bufIn.readLine();//以下是处理异常退出的情况。原因:连接还没断开前,程序给强制关闭,则会报错。处理:判断读取的是否为null,null则退出。if(name==null)break;//提交给服务器writer.println(name);//获取服务器反馈的值String result=reader.readLine();if(result.equals("登陆成功")){System.out.println(result);break;}else{System.out.println("用户名错误");}}//关闭资源bufIn.close();s.close();}}
②服务器端
import java.io.BufferedReader;import java.io.FileReader;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class LoginServer {public static class ClientThread implements Runnable{private Socket s;public ClientThread(Socket socket){this.s=socket;}@Overridepublic void run(){//获取IP地址String ip=s.getInetAddress().getHostAddress();System.out.println(ip+"已连接");try{//获取socket的输入流,获取客户端提交过来的用户名BufferedReader reader=new BufferedReader(new InputStreamReader(s.getInputStream()));//获取socket的输出流,用以向客户端返回数据PrintWriter writer=new PrintWriter(s.getOutputStream(),true);//定义只能错误三次。客户端向服务器发送三次,则服务器也需要有三次的接收。for(int i=0;i<3;i++){//定义一个读取user.txt文件数据的输入流,放在循环里面的原因是因为每次重新登陆都要从头开始校验数据,所以要重新获取user.txt文件里面的数据BufferedReader bufIn=new BufferedReader(new FileReader("D:\\user.txt"));//读取服务器提交的用户名String ClientName=reader.readLine();if(ClientName==null)break;String name=null;//定义一个标记,标记是否存在该用户名boolean isTrue=false;//读取user.txt文件数据while((name=bufIn.readLine())!=null){//如果有存在该用户名则能成功登陆if(ClientName.equals(name)){isTrue=true;break;}}//根据情况,反馈不同信息给客户端if(isTrue){writer.println("登陆成功");System.out.println(ip+"已登陆,用户名:"+ClientName);break;}else{writer.println("登陆失败");System.out.println(ip+"尝试用 "+ClientName+" 用户名登陆");}}s.close();}catch(Exception e){e.printStackTrace();}}}public static void main(String[] args)throws Exception {//实例化一个ServerSocket服务,ServerSocket ss=new ServerSocket(10011);//用循环不断接收客户端的请求while(true){//获取客户端socket的实例Socket s=ss.accept();//开启一个线程处理当前用户,传入对应的socket。这样则可以完成并发处理。new Thread(new ClientThread(s)).start();}}}
7.HTTP协议简单了解
7.1 HTTP请求消息头(向服务器发送请求时就是以下这样的样式)
GET /myServer/demo.html HTTP/1.1 //GET方式提交的 访问指定服务器myServer目录下demo.html文件 用的是HTTP1.1协议(还有个1.0协议)
Host: 127.0.0.1:11000 //访问的主机及端口
Connection: keep-alive //请求模式 keep-alive 保持连接 close完成请求响应后断开
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 //告诉服务器自己能接收什么样的介质类型
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/33.0.1750.146 BIDUBrowser/6.x Safari/537.36 //浏览器信息 表明浏览器身份
Accept-Encoding: gzip,deflate //浏览器的压缩方法
Accept-Language: zh-CN,zh;q=0.8 //支持语言
(此处空一行,下面是请求体)
请求体
7.2 HTTP响应消息头(响应客户端请求时就是以下这样的样式)
HTTP/1.1 200 OK //用的是HTTP1.1协议 200为响应状态码 OK为对应的信息
Server: Apache-Coyote/1.1 //服务器软件及版本信息
Accept-Ranges: bytes //服务器表明是否接收获取某个实体的一部分(例如文件的一部分)的请求 bytes 接受 none不接受
ETag: W/"51-1450254640460" //一个对象的标志值,用于判断对象是否有改动。改动则该值会变。否则不变。
Last-Modified: Wed, 16 Dec 2015 08:30:40 GMT //文件上次修改时间
Content-Type: text/html //响应对象的类型,即是返回对象
Content-Length: 51 //响应对象的长度
Date: Wed, 16 Dec 2015 08:31:27 GMT //日期
Connection: close //请求模式
8.URL和URLConntion
8.1 URL对象
用于处理URL链接。可以通过该URL对象简单便捷的获取到URL链接里面的IP地址,主机名,端口号,文件名,路径,协议名称,查询部分等信息。不用自己手动去截取字符串处理URL链接。
8.1.1 代码实例
URL url = new URL("http://127.0.0.1/pages/test.html?name=xiaoming&age=20");System.out.println("协议名称 :"+url.getProtocol());System.out.println("主机名 :"+url.getHost());System.out.println("端口号 :"+url.getPort());//如果URL里面没有端口号,则返回-1。一般浏览器的做法是,判断为-1则设置为80。System.out.println("路径 :"+url.getPath());System.out.println("文件名 :"+url.getFile());System.out.println("查询部分 :"+url.getQuery());
8.2 URLConntion对象
用HTTP协议封装了Socket,在对象内部帮我们处理连接服务器和取得流等操作。从传输层变到应用层。帮我们封装好请求信息并加上请求消息头发送至服务器。简化操作。
8.2.1 代码实例
URL url = new URL("http://127.0.0.1:8080/pages/test.html");URLConnection conn=url.openConnection();//通过url对象获取URLConnection对象实例InputStream in=conn.getInputStream();//通过URLConnection对象实例获取传递数据的流,实际上,是URLConnection内部的Socket的方法。byte[] buf = new byte[1024];int len = in.read(buf);//读取数据System.out.println(new String(buf,0,len));
9.小知识点
9.1 SocketAddress和InetAddress
9.1.1 SocketAddress对象
封装IP地址和端口
9.1.2 InetAddress
封装IP地址
9.2 ServerSocket的ServerSocket(int port,int backlog)构造方法
第二个参数的意思是队列的最大长度,即同时连接服务器的最大请求个数。例如同时在线人数不得超过10个,则可以设置backlog为10。bakclog的英文意思是积压。
10.域名解析
10.1描述
在浏览器写入一条网址访问对应主机时进行的操作。
10.2 具体操作步骤
①首先,浏览器会查找本地的IP地址和主机名映射列表。在C:\Windows\System32\drivers\etc目录下的hosts文件里面则有记录。
上面的127.0.0.1 localhost则是IP地址和主机名映射
②然后,如果找到,则直接访问。如果在本地找不到映射,则访问在电脑设置好的DNF服务器去查找IP地址和主机名的映射列表。
如果在该DNS服务器有该主机名对应的IP地址,则DNF服务器会返回IP地址。从而能访问到正确的服务器。
10.3 注意
如果浏览器输入的是IP地址而不是主机名,则不会进行域名解析,不会去访问DNF服务器。只有输入的是主机名时,才会走上面的步骤。
- 黑马程序员_java基础之网络编程
- 黑马程序员_java基础-网络编程
- 黑马程序员_Java基础_网络编程
- 黑马程序员_Java基础_网络编程
- 黑马程序员_java基础网络编程
- 黑马程序员_Java基础:网络编程总结
- 黑马程序员_java基础_网络编程
- 黑马程序员_Java基础-网络编程
- 黑马程序员_Java基础_网络编程基础相关
- 黑马程序员_Java 网络编程
- 黑马程序员_Java网络编程
- 黑马程序员_java网络编程
- 黑马程序员_java网络编程
- 黑马程序员_Java网络编程
- 黑马程序员_java网络编程
- 黑马程序员_java 网络编程
- 黑马程序员_java网络编程
- 黑马程序员_java网络编程
- ios控件-UILabel
- iOS懒加载有坑,使用懒加载时应该注意避免
- 初学java 认识 public private protected 修饰符
- 机器学习之k近邻算法
- Scoket
- 黑马程序员_Java基础-网络编程
- java swing 通过hibernate连接数据库的客户端登录
- 初识ACM——中文的信仰
- swift-基础02-注释与数值
- Halcon感兴趣区域填充特定颜色
- STL_8: 迭代器
- delphi ide插件大全
- bzoj2748 音量调节 背包动规
- [BZOJ1911] [Apio2010]特别行动队