黑马程序员_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.TCPUDP

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传输(主要操作类DatagramSocketDatagramPacket

 

5.1 UDP发送端

①建立UDPScoket服务,即是DatagramSocket

②提供数据,封装进DatagramPacket

③通过DatagramSocketsend方法发送数据包

④关闭资源

5.2 UDP服务器端

①定义UDPScoket服务。并需要监听一个端口号,如果不指定则系统会自动分配,一般自己指定,因为不知道系统会分配个什么端口号,而且也方便管理和发送端发送数据。

②定义一个DatagramPacket用于接收发送端发送过来的数据包

③用DatagramSocketreceive方法

④调用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传输(主要操作类SocketServerSocket

服务器和客户端操作同一个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.URLURLConntion

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 SocketAddressInetAddress

9.1.1 SocketAddress对象

封装IP地址和端口

9.1.2 InetAddress

封装IP地址

9.2 ServerSocketServerSocket(int port,int backlog)构造方法

第二个参数的意思是队列的最大长度,即同时连接服务器的最大请求个数。例如同时在线人数不得超过10个,则可以设置backlog10bakclog的英文意思是积压。

 

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培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 产后奶水不足怎么办啊 婴儿吐奶瓣和水怎么办 一岁半宝宝频繁喝夜奶怎么办 婴儿腹泻不吃奶怎么办 八个月宝宝脱水怎么办 宝宝呕吐脱水了怎么办 宝宝腹泻没精神怎么办 小孩拉稀没精神怎么办 宝宝拉稀脱水了怎么办 宝宝发烧还拉肚子怎么办 宝宝发烧后腹泻怎么办 吃海鲜拉肚子了怎么办 孕妇吃海鲜腹泻怎么办 稀饭煮焦了怎么办 8月宝宝拉肚子怎么办 满月宝宝38度怎么办 未满月婴儿拉稀怎么办 未满月宝宝拉稀怎么办 满月的宝宝拉稀怎么办 十个月小孩拉肚子怎么办 十个月宝宝脱水怎么办 宝宝拉肚子老不好怎么办 孩子拉稀老不好怎么办 宝宝拉肚子发呕怎么办 刚出生婴儿拉肚子怎么办 宝宝一岁拉肚子怎么办 刚出生宝宝拉肚子怎么办 宝宝出生五天拉肚子怎么办 生完宝宝拉肚子怎么办? 宝宝6天拉肚子怎么办 十天婴儿拉肚子怎么办 十天小孩拉肚子怎么办 肠炎宝宝一直吐怎么办 初生婴儿老打嗝怎么办 小孩一直发低烧怎么办 婴儿喷奶严重怎么办 婴儿吃奶粉漾奶怎么办 新生儿鼻子溢奶怎么办 宝宝吃奶吐了怎么办 婴儿皮肤干燥脱皮怎么办 新生儿皮肤很红怎么办