java网络编程基础入门.doc

上传人:w****2 文档编号:6645156 上传时间:2020-03-01 格式:DOC 页数:23 大小:716KB
返回 下载 相关 举报
java网络编程基础入门.doc_第1页
第1页 / 共23页
java网络编程基础入门.doc_第2页
第2页 / 共23页
java网络编程基础入门.doc_第3页
第3页 / 共23页
点击查看更多>>
资源描述
1网络编程概述l 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。 l 网络编程 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。 A:有人说,20世纪最伟大的发明不是计算机,而是计算机网络。 还有人说,如果你买了计算机而没有联网,就等于买了电话机而没有接电话线一样。 2 网络模型l 计算机网络之间以何种规则进行通信,就是网络模型研究问题。 l 网络模型一般是指 OSI(Open System Interconnection开放系统互连)参考模型TCP/IP参考模型3 网络参考模型图网络模型7层概述: 1.物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。 2. 数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。 3. 网络层:主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。 4. 传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。 5.会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名) 6.表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。 7.应用层: 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西就是终端应用)。4 网络通信三要素l IP地址:InetAddress 网络中设备的标识,不易记忆,可用主机名l 端口号 用于标识进程的逻辑地址,不同进程的标识l 传输协议 通讯的规则 常见协议:TCP,UDPA:网络模型说完了,我们要进行通讯,需要哪些要素呢? 比如说:我要跟你说话. 第一个条件:我要先找到你 (IP) 第二个条件:你得有接收数据的地方 耳朵 (端口) 第三个条件:我跟你说话,你能接收到,咱按什么方式接收啊,我说英文你懂吗,说韩文你懂吗,不懂是吧,所以我还是说中文把.(协议)5 IP地址l 要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。 l 那么,我们如果获取和操作IP地址呢? 为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress 供我们使用。 A:所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址。按照TCP/IP规定,IP地址用二进制来表示,每个IP地址长32bit,比特换算成字节,就是4个字节。例如一个采用二进制形式的IP地址是“00001010000000000000000000000001”,这么长的地址,人们处理起来也太费劲了。为了方便人们的使用,IP地址经常被写成十进制的形式,中间使用符号“.”分开不同的字节。于是,上面的IP地址可以表示为“10.0.0.1”。IP地址的这种表示法叫做“点分十进制表示法”,这显然比1和0容易记忆得多。 B:IP地址的组成 IP地址 = 网络号码+主机地址A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码特殊地址:127.0.0.1 回环地址,可用于测试本机的网络是否有问题. ping 127.0.0.1 DOS命令 ipconfig:查看本机IP地址xxx.xxx.xxx.0 网络地址xxx.xxx.xxx.255 广播地址A类1.0.0.1-127.255.255.254(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)(2)127.X.X.X是保留地址,用做循环测试用的。B类128.0.0.1-191.255.255.254172.16.0.0-172.31.255.255是私有地址。169.254.X.X是保留地址。C类192.0.0.1-223.255.255.254192.168.X.X是私有地址D类224.0.0.1-239.255.255.254 E类240.0.0.1-247.255.255.2546 InetAddress类的使用l 没有构造方法,那么如何使类提供的功能呢? l 要掌握的功能 获取任意主机:getByName 主机名:getHostName 主机Ip地址:getHostAddress 7 端口号l 物理端口 网卡口l 逻辑端口 我们指的就是逻辑端口 A:每个网络程序都会至少有一个逻辑端口 B:用于标识进程的逻辑地址,不同进程的标识 C:有效端口:065535,其中01024系统使用或保留端口。 通过360可以查看端口号8 协议UDP和TCPl UDP将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快 l TCP建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低总结: udp: 面向无连接。不可靠。速度快。将数据封包传输,数据包最大64k。举例: 聊天留言,在线视频,视频会议,发短信,邮局包裹。tcp: 面向连接。安全可靠效率稍低。通过三次握手确保连接的建立。举例: 下载,打电话,QQ聊天(你在线吗,在线,就回应下,就开始聊天了) 9 Socketl Socket套接字: 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。 l Socket原理机制: 通信的两端都有Socket。 网络通信其实就是Socket间的通信。 数据在两个Socket间通过IO传输。Socket机制图解10 UDP传输l DatagramSocket与DatagramPacketl 建立发送端,接收端。l 建立数据包。l 调用Socket的发送接收方法。l 关闭Socket。l 发送端与接收端是两个独立的运行程序。11 UDP传输-发送端思路l 1:建立udp的socket服务l 2:将要发送的数据封装成数据包l 3:通过udp的socket服务,将数据包发送出l 4:关闭资源12 UDP传输-发送端代码13 UDP传输-接收端思路l 1:建立udp的socket服务. l 2:通过receive方法接收数据l 3:将收到的数据存储到数据包对象中l 4:通过数据包对象的功能来完成对接收到数据进行解析. l 5:可以对资源进行关闭14 UDP传输-接收端代码A:有两个主方法,用几个控制台B:先开启那个方法? 谁先开都行.因为udp的特点是面向无连接. 如果你先开启了发送,那么,它收不到数据而已. 为了演示的方便,先开启接收端. 看到了吗.为什么?等待接收是吧,那句话导致的:ds.receive(dp);该方法是个阻塞是方法.没数据就等着. C:把代码用DOS窗口演示 15 UDP案例l 从键盘录入数据进行发送,如果输入的是886那么客户端就结束输入数据。 l 这个时候完全可以把发送端代码发给大家了,我把接收端代码开启,大家就可以实现聊天了,但是,大家都要看我们的屏幕,即使我把接收端发给大家也是一样的,如何改进呢,使用广播地址即可。 l 最后,把刚才发送和接收程序分别用线程进行封装,完成一个UDP的聊天程序。 l A:这个时候,就需要和io结合起来使用了。还得注意一个问题,这个时候接收端,要一直开启,否则接收一句就关闭了。所以,用死循环,并且,服务不关闭。代码如下: l class SendDemo2 l l public static void main(String args) throws Exception l l DatagramSocket ds = new DatagramSocket(); l l BufferedReader br = new BufferedReader(new InputStreamReader(System.in); l l String line = null; l l while(line=br.readLine()!=null) l l if(886.equals(line) l l break; l l byte by = line.getBytes(); l DatagramPacket dp = new DatagramPacket(by,by.length,InetAddress.getByName(“192.168.1.255),10000); l ds.send(dp); l l l ds.close(); l l l class ReceiveDemo2 l l public static void main(String args) throws Exception l l DatagramSocket ds = new DatagramSocket(10000); /如果10000端口已经被使用了,这个服务起不来l l /我这边是循序接收的啊.无限循环l while(true) l l byte by = new byte1024; l DatagramPacket dp = new DatagramPacket(by,by.length); l l l ds.receive(dp); l l /通过数据包对象的方法获取其中的数据内容,包括地址,端口,数据主体l String ip = dp.getAddress().getHostAddress(); l int port = dp.getPort(); l l byte by2 = dp.getData(); l String text = new String(by2,0,dp.getLength(); l l System.out.println(ip+.+port+.+text); l l l l /关闭资源l /ds.close(); l l l B:用线程封装后的代码如下: l public class SendThread implements Runnable l private DatagramSocket ds;l public SendThread(DatagramSocket ds) l this.ds = ds;l l Overridel public void run() l / 创建UDP发送端的服务l try l / 把键盘录入数据用高效缓冲流封装l BufferedReader br = new BufferedReader(new InputStreamReader(l System.in);l String line = null;l while (line = br.readLine() != null) l if (886.equals(line) l break;l l byte bys = line.getBytes();l / 数据包l DatagramPacket dp = new DatagramPacket(bys, bys.length,l InetAddress.getByName(192.168.1.255), 12345);l / 发送数据l ds.send(dp);l l / 关闭资源l ds.close();l catch (IOException e) l e.printStackTrace();l l l l public class ReceiveThread implements Runnable l private DatagramSocket ds;l public ReceiveThread(DatagramSocket ds) l this.ds = ds;l l Overridel public void run() l try l / 为了循环多次接受l while (true) l / 创建字节数组作为数据包的缓冲区l byte bys = new byte1024;l DatagramPacket dp = new DatagramPacket(bys, bys.length);l / 读取数据包数据l ds.receive(dp);l / 解析数据包l String ip = dp.getAddress().getHostAddress();l int port = dp.getPort();l String text = new String(dp.getData(), 0, dp.getLength();l System.out.println(ip + * + port + * + text);l l catch (IOException e) l e.printStackTrace();l l l l public class ChatDemo l public static void main(String args) throws IOException l DatagramSocket sds = new DatagramSocket();l DatagramSocket rds = new DatagramSocket(12345);l SendThread st = new SendThread(sds);l ReceiveThread rt = new ReceiveThread(rds);l Thread t1 = new Thread(st);l Thread t2 = new Thread(rt);l t1.start();l t2.start();l l 15 TCP传输l Socket和ServerSocketl 建立客户端和服务器端l 建立连接后,通过Socket中的IO流进行数据的传输l 关闭socket l 同样,客户端与服务器端是两个独立的应用程序。TCP传输-客户端思路l 1:建立客户端的Socket服务,并明确要连接的服务器。 l 2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流. l 3:通过Socket对象的方法,可以获取这两个流l 4:通过流的对象可以对数据进行传输5:如果传输数据完毕,关闭资源TCP传输-客户端代码16 TCP传输-服务器端思路l 1:建立服务器端的socket服务,需要一个端口l 2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信 l 3:通过客户端的获取流对象的方法,读取数据或者写入数据l 4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的TCP传输-服务器端代码A:客户端和服务器都写好后,先开启谁呢? 开启服务器端。因为服务器如果不开启,客户端就不知道和谁进行连接啊。 18 TCP传输案例l 服务器给客户端反馈 l 客户端键盘录入,服务器输出到控制台 l 客户端键盘录入,服务器输出文本文件 l 客户端文本文件,服务器输出到控制台 l 客户端文本文件,服务器输出文本文件 l 上传图片案例 l 服务器的代码用线程进行封装,这样可以模拟一个同时接收多人上传文件的服务器。(用循环也可以但是效率低,是单线程的程序)l A:代码如下 l 客户端追加代码: l /获取服务端的东西l InputStream is = s.getInputStream(); l byte by = new byte1024; l int len = is.read(by); l l String text = new String(by,0,len); l System.out.println(server:+text); l 服务器端追加代码: l /给客户端回馈数据l OutputStream out = s.getOutputStream(); l out.write(哥们已收到.getBytes();l B:代码如下 l public static void main(String args) throws Exception l / 建立客户端Socket服务,并去进行目的地址连接l Socket s = new Socket(192.168.1.100, 11111);l BufferedReader br = new BufferedReader(new InputStreamReader(System.in);l BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(l s.getOutputStream();l BufferedReader brServer = new BufferedReader(new InputStreamReader(l s.getInputStream();l String line = null;l while (line = br.readLine() != null) l if (over.equals(line) l break;l l bw.write(line);l bw.flush();l String serverText = brServer.readLine();l System.out.println(serverText);l l / out用关吗,它是有s建立的,s关闭了,它就关闭了,所以不用单独关l s.close();l l public static void main(String args) throws Exception l / 1:建立服务端对象,监听一个端口l ServerSocket ss = new ServerSocket(11111);l / 2:通过accept方法获取客户端对象l Socket s = ss.accept();l String ip = s.getInetAddress().getHostAddress();l System.out.println(ip + .connected);l BufferedReader br = new BufferedReader(new InputStreamReader(l s.getInputStream();l BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(l s.getOutputStream();l String line = null;l while (line = br.readLine() != null) l / 打印一下,看到底传递过来了什么数据l System.out.println(line);l bw.write(line.toUpperCase();l l / 5:关闭资源l s.close();l ss.close();l l 这个时候,出现问题了,我们需要考虑什么原因产生的。 l 1:首先要分析数据是否传递出去,以及数据是否接受到。 l 没发出去,因为out有缓冲区,必须刷新一下.两端都要刷。 l 2:还不行,其实是读取到了,但是问题在于readLine读取数据的时候,会根据换行来判断,l 到此为止,它不知道你读取到结尾了.修改后的代码如下:l 客户端 l bw.write(line + rn);l bw.flush(); l l 服务器: l bw.write(line.toUpperCase() + rn);l bw.flush();l 服务器和客户端都会关闭,因为他是面向连接的。 l 到此为止,发现我们的数据需要刷新和换行,所以采用PrintWwriter改进。 l 定义结束标记: l 因为while(line=br.readLine()!=null) readLine()是阻塞式的,它还在等着读,对吧. l 但是,你客户端流一结束,就相当于给服务端写了一个结束标记.这样的话,服务端就结束了. l 那么,大家,我们稍微总结下. l TCP传输容易出现,客户端和服务端都等待的情况,因为客户端和服务端有阻塞式方法存在,比如read,readLine方法.所以,必须要定义结束标记. l read要定义-1结束标记,readLine需要定义回车结束标记,和-1结束标记. l 因为readLine底层调用了read. l C:代码如下 l public class UploadClient l public static void main(String args) throws IOException l Socket s = new Socket(192.168.1.100, 12321);l BufferedReader br = new BufferedReader(new FileReader(java.txt);l PrintWriter pw = new PrintWriter(s.getOutputStream(), true);l String line = null;l while (line = br.readLine() != null) l pw.println(line);l l / 第一种解决方案 假如数据里面有一行是over就悲剧了l / pw.println(over);l / 第二种解决方案l / s.shutdownOutput();l / 接收服务器返回l BufferedReader brIn = new BufferedReader(new InputStreamReader(l s.getInputStream();l String str = brIn.readLine();l System.out.println(server: + str);l br.close();l s.close();l l l public static void main(String args) throws IOException l ServerSocket ss = new ServerSocket(12321);l Socket s = ss.accept();l String ip = s.getInetAddress().getHostAddress();l System.out.println(ip + .connected);l BufferedReader br = new BufferedReader(new InputStreamReader(l s.getInputStream();l PrintWriter pw = new PrintWriter(new FileWriter(server.txt), true);l String line = null;l while (line = br.readLine() != null) l / if (over.equals(line) l / break;l / l pw.println(line);l l PrintWriter out = new PrintWriter(s.getOutputStream(), true);l out.println(上传成功);l pw.close();l s.close();l ss.close();l l D:代码如下 l 客户端不改。 l 把服务器进行封装。 l public class UserThread implements Runnable l private Socket s;l public UserThread(Socket s) l this.s = s;l l Overridel public void run() l /同一个客户端可以发多个文件的,避免产生覆盖,对每个文件进行重写命名l / int count = 0;l String ip = s.getInetAddress().getHostAddress();l try l System.out.println(ip + .connected);l BufferedReader br = new BufferedReader(new InputStreamReader(l s.getInputStream();l / 为了文件不覆盖l File dir = new File(c:txt);l if (!dir.exists() l dir.mkdir();l l / File file = new File(dir, ip + ( + (count+) + ) + .txt);l / / 但是同一台机子上可以继续传l / while (file.exists() l / file = new File(dir, ip + ( + (count+) + ) + .txt);l / l File file = new File(dir, ip + .txt);l PrintWriter pw = new PrintWriter(new FileWriter(file), true);l String line = null;l while (line = br.readLine() != null) l pw.println(line);l l PrintWriter out = new PrintWriter(s.getOutputStream(), true);l out.println(上传成功);l pw.close();l s.close();l catch (Exception e) l throw new RuntimeException(ip + .);l l l l 测试代码: l public static void main(String args) throws Exceptionl l ServerSocket ss = new ServerSocket(10011);l while(true)l l Socket s = ss.accept();l /将客户端封装成线程l new Thread(new UserThread(s).start();l l /ss不能关闭,等待着l l 其实,服务器最底层使用的就是三项基本技术: l Socket,ServerSocket l 多线程l IO 16 TCP传输容易出现的问题l 客户端连接上服务端,两端都在等待,没有任何数据传输。 l 通过例程分析: 因为read方法或者readLine方法是阻塞式。l 解决办法: 自定义结束标记 使用shutdownInput,shutdownOutput方法。
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 临时分类 > 人文社科


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!