黑马程序员—【Java基础篇】之网络编程
2015-04-28 15:28
288 查看
------- android培训、java培训、期待与您交流!
---------
伙伴们,这篇分享网络编程,开始,跑,哈哈。
参考模型图:
UDP传输协议示例:
TCP传输协议示例:
UDP传输应用练习:
TCP传输应用练习:
应用2:
练习1:
图片说明:
host的应用:
(1)可屏蔽一些恶意网址,即将对应的映射关系写入hosts中,将IP地址改为本机的回环地址,那么会直接找到hosts,就不会将请求发送出去了。
(2)可以提高上网速度。
好了,大神们,现在是下午17:11分,肚子有些饿了,准备晚餐去了,有一起的吗?那就吃饭饭了,嘎嘎。
------- android培训、java培训、期待与您交流!
---------
---------
伙伴们,这篇分享网络编程,开始,跑,哈哈。
一、网络编程
1、网络模型
/** (1)OSI参考模型 (2)TCP/IP参考模型 */
参考模型图:
2、网络通讯要素
网络通讯要素主要包括:IP、端口号和传输协议。/** (1)IP地址:InetAddress a、网络中设备的标识 b、不易记忆,可用主机名 c、本地回环地址:127.0.0.1 主机名:localhost (2)端口号 a、用于标识进程的逻辑地址,不同进程的标识 b、有效端口:0~65535,其中0~1024系统使用或保留端口。 (3)传输协议 a、通讯的规则 b、常见协议:TCP,UDP */
二、传输协议
1、概述
/** 传输协议 a、通讯的规则 b、常见协议:TCP,UDP */
2、Socket
<pre name="code" class="java">/** 1、定义 Socket就是为网络服务提供的一种机制。通信的两端都有Socket。 2、特点 a、网络通信其实就是Socket间的通信。 b、数据在两个Socket间通过IO传输。 */
3、TCP和UDP
<span style="font-size:14px;">/** (1)UDP a、将数据及源和目的封装成数据包中,不需要建立连接。 b、每个数据报的大小在限制在64k内因无连接,是不可靠协议 c、不需要建立连接,速度快 (2)TCP a、建立连接,形成传输数据的通道。 b、在连接中进行大数据量传输 c、通过三次握手完成连接,是可靠协议 d、必须建立连接,效率会稍低 */</span>
UDP传输协议示例:
/** 需求:通过udp传输方式,将一段文字数据发送出去。, 定义一个udp发送端。 思路: (1)建立updsocket服务。 (2)提供数据,并将数据封装到数据包中。 (3)通过socket服务的发送功能,将数据包发出去。 (4)关闭资源。 */ class UdpSend { public static void main(String[] args) throws Exception { //1,创建udp服务。通过DatagramSocket对象。 DatagramSocket ds = new DatagramSocket(8888); //2,确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress address, int port) byte[] buf = "udp ge men lai le ".getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),10000); //3,通过socket服务,将已有的数据包发送出去。通过send方法。 ds.send(dp); //4,关闭资源。 ds.close(); } } /** 需求:定义一个应用程序,用于接收udp协议传输的数据并处理的,定义udp的接收端。 思路: (1)定义udpsocket服务。 通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识,方便于明确哪些数据过来该应用程序可以处理。 (2)定义一个数据包,因为要存储接收到的字节数据。 因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。 (3)通过socket服务的receive方法将收到的数据存入已定义好的数据包中。 (4)通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。 (5)关闭资源。 */ class UdpRece { public static void main(String[] args) throws Exception { //1,创建udp socket,建立端点。 DatagramSocket ds = new DatagramSocket(10000); while(true) { //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); } //5,关闭资源 //ds.close(); } } /** 总结: (1)DatagramSocket与DatagramPacket; (2)建立发送端,接收端; (3)建立数据包; (4)调用Socket的发送接收方法。 (5)关闭Socket。 发送端与接收端是两个独立的运行程序。 */<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
TCP传输协议示例:
/** 分析: (1)Socket和ServerSocket (2)建立客户端和服务器端 (3)建立连接后,通过Socket中的IO流进行数据的传输 (4)关闭socket 注意事项:客户端与服务器端是两个独立的应用程序。 /** 客户端, 通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。 需求:给服务端发送给一个文本数据。 步骤: (1)创建Socket服务。并指定要连接的主机和端口。 */ import java.io.*; import java.net.*; class TcpClient { public static void main(String[] args) throws Exception { //创建客户端的socket服务。指定目的主机和端口 Socket s = new Socket("192.168.1.254",10003); //为了发送数据,应该获取socket流中的输出流。 OutputStream out = s.getOutputStream(); out.write("tcp ge men lai le ".getBytes()); s.close(); } } /** 需求:定义端点接收数据并打印在控制台上。 服务端: (1)建立服务端的socket服务。ServerSocket(); 并监听一个端口。 (2)获取连接过来的客户端对象。 通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法阻塞式的。 (3)客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。 并打印在控制台。 (4)关闭服务端。(可选) */ class TcpServer { public static void main(String[] args) throws Exception { //建立服务端socket服务。并监听一个端口。 ServerSocket ss = new ServerSocket(10003); //通过accept方法获取连接过来的客户端对象。 while(true) { Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+".....connected"); //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。 InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf,0,len)); s.close();//关闭客户端. } //ss.close(); } } */<span style="font-size:14px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
UDP传输应用练习:
/** 需求:编写一个聊天程序,有收数据的部分和发数据的部分,这两部分需要同时执行。 分析:那就需要用到多线程技术,一个线程控制收,一个线程控制发。 因为收和发动作是不一致的,所以要定义两个run方法,而且这两个方法要封装到不同的类中。 */ import java.io.*; import java.net.*; 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) { byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10002); ds.send(dp); if("886".equals(line)) break; } } 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()); if("886".equals(data)) { System.out.println(ip+"....离开聊天室"); break; } System.out.println(ip+":"+data); } } catch (Exception e) { throw new RuntimeException("接收端失败"); } } } class ChatDemo { public static void main(String[] args) throws Exception { DatagramSocket sendSocket = new DatagramSocket(); DatagramSocket receSocket = new DatagramSocket(10002); new Thread(new Send(sendSocket)).start(); new Thread(new Rece(receSocket)).start(); } }
TCP传输应用练习:
import java.io.*; import java.net.*; /** 需求: 演示tcp的传输的客户端和服务端的互访,客户端给服务端发送数据,服务端收到后,给客户端反馈信息。 客户端: (1)建立socket服务。指定要连接主机和端口。 (2)获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。 (3)获取socket流中的输入流,将服务端反馈的数据获取到,并打印。 (4)关闭客户端资源。 */<pre name="code" class="java">class TcpClient2 { public static void main(String[] args)throws Exception { Socket s = new Socket("192.168.1.254",10004); 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 TcpServer2 { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10004); Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"....connected"); 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(); Thread.sleep(10000); out.write("哥们收到,你也好".getBytes()); s.close(); ss.close(); } }
4、应用
应用1:/* * 需求:并发上传图片 */ import java.io.*; import java.net.*; //客户端 class PicClient { 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("图片格式错误,请重新选择!"); return; } //对文件大小进行判断 if (file.length()>1024*1024*5) { System.out.println("你上传的文件过大,居心叵测!"); return; } //创建服务 Socket s=new Socket("localhost",10000); //读取图片数据 FileInputStream fis=new FileInputStream(file); //用Socket服务输出流写入数据 OutputStream out =s.getOutputStream(); BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); byte[] buf=new byte[1024]; int len=0; while ((len=fis.read(buf))!=-1) { out.write(buf,0,len); } //结束标记,表示文件数据已经上传完了 s.shutdownOutput(); String info=in.readLine();//读取返回信息 System.out.println(info); fis.close();//关流 s.close(); } } //服务端 class PicServer { public static void main(String[] args)throws Exception { //创建服务,监听端口 ServerSocket ss=new ServerSocket(10000); while (true) { //获取客户端对象 Socket s=ss.accept(); //客户端执行线程 new Thread(new PicThread(s)).start(); } //ss.close(); } } //利用多线程实现并发上传 class PicThread implements Runnable { private Socket s; PicThread(Socket s) { this.s=s; } public void run() { int count=1; //获取客户端ip String ip=s.getInetAddress().getHostAddress(); try { System.out.println(ip+" connected....."); //通过客户端的读取流读取数据 InputStream in=s.getInputStream(); //文件保存路径 File dir =new File("C:\\Users\\asus\\Desktop"); //文件名 File file=new File(dir,ip+".jpg"); //判断文件是否存在 while(file.exists()) { file=new File(dir,ip+"("+(count++)+").jpg"); } //将数据写入到指定文件中 FileOutputStream fos=new FileOutputStream(file); byte[] buf=new byte[1024]; int len=0; while ((len=in.read(buf))!=-1) { fos.write(buf,0,len); } //将收到图片数据的信息返回给客户端 OutputStream out=s.getOutputStream(); out.write("上传成功!".getBytes()); fos.close();//关流 s.close(); } catch (Exception e) { throw new RuntimeException(ip+"图片上传失败"); } } } <pre name="code" class="java">小结: 1、一对一(单线程)上传的思路: 客户端 a、服务端点。 b、读取客户端已有的图片数据 c、通过Socket输出流将数据发给服务端 d、读取服务端反馈信息。 e、关闭 服务端 a、服务端服务,并监听窗口 b、获取客户端对象,并获取客户ip c、读取客户端输入流数据 d、写入文件 e、用客户端输出流反馈信息 f、关流 2、单线程的服务端有个局限性。 当A客户端连接上以后,被服务端获取到。服务端执行具体流程。这时B客户端连接,只能等待。因为服务端还没有处理完A客户端的请求。还没有循环回来执行下一次accept方法。所以,暂时获取不到B客户端对象。 那么为了可以让多个客户端同时并发访问服务端。服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。 如何定义线程呢? 只要明确了每一个客户端要在服务端执行的代码,如示例所示将该代码存入run方法即可。 */<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
应用2:
import java.io.*; import java.net.*; //客户端 class LoginClient { public static void main(String[] args) throws Exception { //创建服务 Socket s=new Socket("localhost",10000); //键盘录入 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); //用Socket服务输出流写入数据 PrintWriter out =new PrintWriter(s.getOutputStream(),true ); //接收服务器返回的信息 BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); String line=null; for(int x=0;x<3;x++) { line=br.readLine();//读取键盘录入 if (line==null) { break;//如果键盘没有输入,则直接结束 } out.println(line);//将数据写入流中 String info=in.readLine();//读取返回信息 System.out.println(info); if (info.contains("欢迎"))//--------------- { break;//如果登录成功,就跳出循环 } } br.close();//关流 s.close(); } } //服务端 class LoginServer { public static void main(String [] args)throws Exception { //创建服务,监听端口 ServerSocket ss=new ServerSocket(10000); while (true) { //获取客户端对象 Socket s=ss.accept(); //客户端执行线程 new Thread(new LoginThread(s)).start(); } //ss.close(); } } //利用多线程实现并发登录 class LoginThread implements Runnable { private Socket s; LoginThread(Socket s) { this.s=s; } public void run() { //获取客户端ip String ip=s.getInetAddress().getHostAddress(); System.out.println(ip+" connected....."); try { for (int x=0;x<3 ;x++ ) { //通过客户端的读取流读取数据 BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); //读取数据库中的数据,这里用文件来表示数据库 BufferedReader br=new BufferedReader(new FileReader("users.txt")); String line=in.readLine();//读取客户端数据 if (line==null)//-------------- { break;//如果客户端没有发送数据,则跳出循环 } String data=null; boolean flag=false;//设置标记 //读取数据库中的用户数据 while ((data=br.readLine())!=null) { if (line.equals(data)) { flag=true;//如果用户存在,则将标记设为true break; } } //将数据写入到指定文件中 PrintWriter out=new PrintWriter(s.getOutputStream(),true); if (flag) { System.out.println(line+",已登陆!"); out.println(line+",欢迎光临!"); break;//----------- } else { System.out.println(line+",尝试登陆!"); out.println(line+",用户名不存在!"); } } s.close();//关流 } catch (Exception e) { throw new RuntimeException("用户登陆失败"); } } }<pre name="code" class="java">/** 小结: (1)浏览器是一个标准的客户端,它可以对服务端传送过来的数据消息进行解析,把符合应用层协议的消息部分解析后,将头信息拆包掉,传送到应用层,只保留了正确的正文主题部分显示在主体部分上。 (2)而由于使用java编译是在传输层和网际层处理的,所以,会接受到全部的消息,包含了头消息。而浏览器处于应用层,已将发送来的头消息去除,只留下了主体信息。 */<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
三、URL和URLConnection
1、概述
/** (1)URL: URI:范围更大,条形码也包含于此范围 URL:范围较小,即域名 1)方法 a、构造函数:URL(String protocol,String host,int port,String file);//根据指定 protocol、host、port号和 file 创建 URL对象。 b、String getProtocol();//获取协议名称 c、String getHost();//获取主机名 d、int getPort();//获取端口号 e、String getFile();//获取URL文件名 f、String getPath();//获取此URL的路径部分 g、String getQuery();//获取此URL的查询部,客户端传输的特定信息 注:一般输入网址,是不带端口号的,此时可进行获取,通过获取网址返回的port,若port为-1,则分配一个默认的80端口,如 int port = getPort(); if(port == -1) port = 80; (2)URLConnection 1)方法: a、URLConnection openConnection();//用URL调用此方法,返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。 b、InputStream getInputStream();//获取输入流 c、OutputStream getOutputStream();//获取输出流 */
练习1:
/* * 自定义浏览器,显示网页信息 */ import java.io.*; import java.awt.*; import java.awt.event.*; import java.net.*; class MyIEGUIDemo { //定义所需组件引用 private Frame f; private Button but,bok; private TextField tf; private TextArea ta; //构造函数 MyIEGUIDemo() { init(); } //窗体基本设置于功能实现 public void init() { //组件实例化 f=new Frame("我的Window"); but=new Button("跳转"); tf=new TextField(50); ta=new TextArea(25,60); //基本设置 f.setBounds(300,150,500,500); f.setLayout(new FlowLayout()); //添加组件 f.add(tf); f.add(but); f.add(ta); //窗体事件 myEvent(); //窗体显示 f.setVisible(true); } //注册事件 public void myEvent() { //窗体关闭功能 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); //“跳转”按钮事件 but.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { showFile();//显示网页内容在文本区中 } }); //文本框键盘事件 tf.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { //如果键盘按下Enter键,就将网页内容显示在文本区中 if(e.getKeyCode()==KeyEvent.VK_ENTER) showFile(); } }); } //显示网页内容 private void showFile() { ta.setText(""); String path=tf.getText();//获取输入的路径 try { //封装地址对象 URL url =new URL(path); 连接网页服务器 URLConnection conn=url.openConnection(); //读取流,用于读取服务器返回数据 InputStream in=conn.getInputStream(); byte[] buf=new byte[1024*1024]; int len=in.read(buf); //将数据显示在文本区中 ta.append(new String(buf,0,len)); } catch (Exception e) { throw new RuntimeException("连接"+path+"网站失败"); } } public static void main(String[] args) { //运行窗体 new MyIEGUIDemo(); } }
2、小知识点扩展
/** (1)InetSocketAddress对象(IP+端口) (2)ServerSocket对象中的构造函数: ServerSocket(int port,int backlog),其中的backlog表示队列的最大长度,即最多连入客户端的个数,即最大连接数。 (3)在进行浏览器输入网址访问一台主机所做的操作: 如http://192.168.1.100:8080/myweb/myIE.html,一般直接输入主机名:http://baidu.com.cn等,那么如何通过主机名获取IP地址,从而连接到这台主机的呢?这就需要将主机名翻译成IP地址,即域名解析:DNS。 在进行访问的时候,会现在本地的hosts文件(C:\WINDOWS\system32\drivers\etc\hosts)中找对应的映射,若有,则直接返回请求,若无,则到公网的映射列表即DNS中找对应的映射,找到后,将主机名对应的IP地址返回给本机,本机通过这个IP地址找到对应的服务器。 */
图片说明:
host的应用:
(1)可屏蔽一些恶意网址,即将对应的映射关系写入hosts中,将IP地址改为本机的回环地址,那么会直接找到hosts,就不会将请求发送出去了。
(2)可以提高上网速度。
好了,大神们,现在是下午17:11分,肚子有些饿了,准备晚餐去了,有一起的吗?那就吃饭饭了,嘎嘎。
------- android培训、java培训、期待与您交流!
---------
相关文章推荐
- 黑马程序员java基础篇----网络编程总结
- 黑马程序员—21—java基础:有关网络编程的学习笔记和学习心得体会
- 黑马程序员Java学习日记(8)网络编程
- 黑马程序员——————java中的网络编程
- 黑马程序员_java 网络编程
- 黑马程序员——java高新技术——网络编程
- 黑马程序员_Java基础_网络编程
- 黑马程序员_java网络编程
- 黑马程序员-java网络编程
- 黑马程序员--java基础:网络编程
- 黑马程序员<Java笔记<GUI 网络编程反射>>
- 『黑马程序员』---java--网络编程--网络编程概念+UDP基础
- 黑马程序员--java 基础之网络编程 --09
- 黑马程序员_java10_网络编程
- 黑马程序员--第二阶段--JAVA网络编程--第23天
- 黑马程序员_Java基础_网络编程_UDP传输协议编程,控制台聊天程序
- 黑马程序员_Java网络编程
- 黑马程序员:JAVA网络编程
- 黑马程序员----Java网络编程
- 黑马程序员--JAVA网络编程