网络编程——第二部分
第一讲,第二讲:网络编程(TCP-上传图片),第24天-02-网络编程(TCP-客户端并发上传图片)
一,要求:实现用TCP客户端实现并发上传图片。
- 客户端:
- 创建服务短点。
- 读取客户端已有的图片数据。
- 通过 Socket 输出流将数据发送给服务端。
- 关闭客户端资源。
- 服务端:
- 创建服务端服务,并监听指定端口。
- 获取客户端对象,并获取客户端IP地址。
- 读取客户端输入数据
- 写入文件。
- 断开资源连接。
- 客户端:
二,单线程服务的局限性:当A客户端连接上以后,被服务端获取到。服务端执行具体流程。这时B客户端连接,只能等待。因为服务端还没有处理完A客户端的请求。还没有循环回来执行下一次accept方法。所以,暂时获取不到B客户端对象。
三,解决办法:服务端将每个客户端封装到一个单独的线程中,,将客户端要在服务端执行的代码存入run方法即可。
四,练习代码:
客户端:
1 import java.io.*; 2 import java.net.*; 3 4 5 6 //创建客户端上传图片 7 public class PicClinet { 8 public static void main(String[] args) { 9 10 //定义图片文件夹 11 File file = new File("F:\\Image\\BingWallpaper-2014-10-26.jpg"); 12 13 //定义客户端套接字 14 Socket s = null; 15 16 //获取客户端输入流 17 InputStream is = null; 18 19 //客户端输出流 20 OutputStream os = null; 21 22 //文件输入流 23 FileInputStream fis = null; 24 25 26 //实例化对象,捕获异常 27 try{ 28 29 s = new Socket(InetAddress.getLocalHost(),10000); 30 31 is = s.getInputStream(); 32 33 os = s.getOutputStream(); 34 35 fis = new FileInputStream(file); 36 }catch(FileNotFoundException e){ 37 System.out.println("文件不存在"+e.toString()); 38 }catch(UnknownHostException e){ 39 System.out.println("与服务器连接失败"+e.toString()); 40 }catch(IOException e){ 41 System.out.println("IO异常"+e.toString()); 42 } 43 44 45 //使用缓冲区,提高效率 46 BufferedOutputStream bos = new BufferedOutputStream(os); 47 BufferedInputStream bis = new BufferedInputStream(is); 48 BufferedInputStream bis_file = new BufferedInputStream(fis); 49 50 //定义字节数组,保存读入的内容 51 byte b[] = new byte[1024]; 52 53 //标志读入的长度 54 int len = 0; 55 56 //进行读取,捕获异常 57 try { 58 59 //循环读取 60 while((len=bis_file.read(b))!=-1){ 61 62 //传到服务器 63 bos.write(b,0,len); 64 65 //刷新 66 bos.flush(); 67 } 68 69 //关闭输出流 70 s.shutdownOutput(); 71 72 //接受服务端提示消息 73 len = bis.read(b); 74 } catch (IOException e) { 75 System.out.println("读取发生错误"+e.toString()); 76 } 77 78 //打印提示消息 79 System.out.println(new String(b,0,len)); 80 } 81 }
服务端线程:
1 import java.io.*; 2 import java.net.*; 3 4 5 //创建线程类,实现多客户端并发上传文件 6 public class PicThread implements Runnable{ 7 8 //定义Socket套接字,表示连入的客户端 9 Socket s = null; 10 11 //构造方法 12 public PicThread(Socket s){ 13 this.s = s; 14 } 15 16 //覆写run() 方法,将实际要执行的代码放入 17 @Override 18 public void run(){ 19 20 //获取客户端输入输出流 21 InputStream is = null; 22 OutputStream os = null; 23 24 25 //本地文件输出流 26 FileOutputStream fos = null; 27 28 File file = new File("E://"+s.getInetAddress().getHostAddress()+".jpg"); 29 30 31 //实例化对象,进行异常处理 32 try{ 33 fos = new FileOutputStream(file); 34 35 is = s.getInputStream(); 36 37 os = s.getOutputStream(); 38 39 }catch(FileNotFoundException e){ 40 System.out.println("目录不存在"+e.toString()); 41 }catch(IOException e){ 42 System.out.println("IO异常"+e.toString()); 43 } 44 45 46 //缓冲区提高效率 47 BufferedInputStream bis = new BufferedInputStream(is); 48 49 BufferedOutputStream bos = new BufferedOutputStream(os); 50 51 BufferedOutputStream bos_file = new BufferedOutputStream(fos); 52 53 54 //定义字节数组保存内容 55 byte b[] = new byte[1024]; 56 57 //记录读取的长度 58 int len = 0; 59 60 //读取 61 try { 62 63 //循环从客户端读取内容 64 while((len=bis.read(b))!=-1){ 65 66 //写入本地文件 67 bos_file.write(b,0,len); 68 69 //刷新 70 bos_file.flush(); 71 } 72 73 //关闭资源 74 bos_file.close(); 75 76 //给出客户端上传成功提示 77 bos.write("上传成功!".getBytes()); 78 bos.flush(); 79 } catch (IOException e) { 80 System.out.println("IO异常!"+e.toString()); 81 } 82 } 83 }
服务器端:
1 import java.io.*; 2 import java.net.*; 3 4 //创建服务器端,接受客户端发来的图片数据 5 public class PicServ { 6 public static void main(String[] args) { 7 8 //创建服务端套接字 9 ServerSocket ss = null; 10 11 //客户端套接字 12 Socket s = null; 13 14 //实例化服务端 15 try { 16 ss = new ServerSocket(10000); 17 18 } catch (IOException e) { 19 20 } 21 22 23 //循环接受客户端请求 24 while(true){ 25 try { 26 s=ss.accept(); 27 } catch (IOException e) { 28 System.out.println("IO异常"+e.toString()); 29 } 30 31 //创建线程,将客户端套接字传入 32 new Thread(new PicThread(s)).start(); 33 } 34 35 } 36 }
第三讲:网络编程(TCP-客户端并发登录)
一,需求:实现客户端并发登陆:客户端通过键盘录入用户名,服务端对这个用户名进行校验。 如果该用户存在,在服务端显示xxx,已登陆;并在客户端显示xxx,欢迎光临。 如果用户不存在,在服务端显示xxx,尝试登陆;并在客户端显示xxx,该用户不存在。 最多就登录三次。
二,代码练习:
客户端:
1 import java.io.*; 2 import java.net.*; 3 4 //创建客户端实现登陆 5 public class LoginClient { 6 public static void main(String[] args) { 7 8 //客户端套接字 9 Socket s = null; 10 11 12 //客户端输入流 13 InputStream is = null; 14 15 //客户端输出流 16 OutputStream os = null; 17 18 19 //实例化对象 20 try{ 21 s = new Socket(InetAddress.getLocalHost(),10000); 22 23 is = s.getInputStream(); 24 25 os = s.getOutputStream(); 26 27 }catch(UnknownHostException e){ 28 System.out.println("主机未找到异常"+e.toString()); 29 }catch(IOException e){ 30 System.out.println("io异常"+e.toString()); 31 } 32 33 34 //缓冲流提高效率 35 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 36 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); 37 38 BufferedReader br_key = new BufferedReader(new InputStreamReader(System.in)); 39 40 41 42 try{ 43 //接收键盘一行输入 44 String line; 45 46 //三次登陆机会 47 for(int i = 0;i<3;i++){ 48 49 //读入键盘输入 50 line = br_key.readLine(); 51 52 //判断是否为空 53 if(line==null) 54 break; 55 56 //向服务器端写入数据 57 bw.write(line); 58 bw.newLine(); 59 bw.flush(); 60 61 //获取服务端反馈信息 62 line = br.readLine(); 63 64 //判断是否登陆成功 65 if(line.contains("欢迎")){ 66 System.out.println(line); 67 break; 68 } 69 70 //打印服务端消息 71 System.out.println(line); 72 } 73 }catch(IOException e){ 74 System.out.println("IO异常11"+e.toString()); 75 } 76 77 try{ 78 br.close(); 79 s.close(); 80 }catch(IOException e){ 81 System.out.println("关闭异常"+e.toString()); 82 } 83 } 84 }
线程类:
1 import java.net.*; 2 import java.io.*; 3 4 5 //创建线程类对客户端服务 6 public class LoginThread implements Runnable{ 7 8 //表示客户端套接字 9 private Socket s = null; 10 11 //构造方法 12 public LoginThread(Socket s){ 13 this.s = s; 14 } 15 16 17 //覆写run()方法 18 @Override 19 public void run(){ 20 21 //客户端输入输出流 22 InputStream is = null; 23 OutputStream os = null; 24 25 //获取本地用户信息 26 File file = new File("E:/info.txt"); 27 28 29 try{ 30 is = s.getInputStream(); 31 os = s.getOutputStream(); 32 33 }catch(FileNotFoundException e){ 34 System.out.println("文件不存在"+e.toString()); 35 }catch(IOException e){ 36 System.out.println("IO异常22"+e.toString()); 37 } 38 39 //缓冲流提高效率 40 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 41 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); 42 43 //只有三次登陆机会 44 for(int i = 0;i<3;i++){ 45 46 //接受客户端输入 47 String line = null; 48 //本地文件读取结果 49 String name = null; 50 51 try{ 52 FileReader fis = new FileReader(file); 53 BufferedReader br_file = new BufferedReader(fis); 54 line = br.readLine(); 55 56 //如果客户端输入为空结束循环 57 if(line == null) 58 break; 59 60 //判断是否存在用户 61 while((name=br_file.readLine())!=null){ 62 63 //如果存在给出提示 64 if(line.equals(name)){ 65 bw.write("欢迎光临"+name); 66 bw.newLine(); 67 bw.flush(); 68 break; 69 } 70 } 71 72 //如果不存在给出提示 73 bw.write("失败"); 74 bw.newLine(); 75 bw.flush(); 76 77 //关闭资源 78 br_file.close(); 79 80 }catch(IOException e){ 81 System.out.println("IO异常33"+e.toString()); 82 } 83 } 84 } 85 }
服务器端:
1 import java.io.*; 2 import java.net.*; 3 4 5 //创建服务器端 6 public class LoginServ { 7 public static void main(String[] args) { 8 //服务器套接字 9 ServerSocket ss = null; 10 11 //客户端套接字 12 Socket s = null; 13 14 //实例化 15 try{ 16 ss = new ServerSocket(10000); 17 }catch(IOException e){ 18 System.out.println("初始化失败"+e.toString()); 19 } 20 21 22 //循环接受客户端服务 23 while(true){ 24 try{ 25 s = ss.accept(); 26 }catch(IOException e){ 27 System.out.println("接受客户端请求失败"+e.toString()); 28 } 29 30 //创建线程,处理客户端请求 31 new Thread(new LoginThread(s)).start(); 32 } 33 } 34 }
第四讲:网络编程(浏览器客户端-自定义服务端)
代码练习:
1 import java.io.*; 2 import java.net.*; 3 4 5 public class ServDemo { 6 public static void main(String[] args) { 7 //服务器端套接字 8 ServerSocket ss = null; 9 10 //客户端套接字表示 11 Socket s = null; 12 13 //客户端输出流 14 PrintWriter pw = null; 15 16 //实例化 17 try{ 18 ss = new ServerSocket(11000); 19 20 s = ss.accept(); 21 22 pw = new PrintWriter(s.getOutputStream(),true); 23 }catch(IOException e){ 24 System.out.println("连接异常"+e.toString()); 25 } 26 27 //向客户端发送消息 28 pw.println("<font color='red' size='7'>客户端你好!</font>"); 29 try { 30 s.close(); 31 ss.close(); 32 } catch (IOException e) { 33 // TODO Auto-generated catch block 34 e.printStackTrace(); 35 } 36 } 37 }
第五讲:网络编程(浏览器客户端-Tomcat服务端)
一,客户端浏览器发送的内容:
http:请求消息头:
GET / HTTP/1.1 =======请求方法--目标--协议=====
Accept: */* ==接受的文件格式==
Accept-Language: zh-CN ==接收的语言==
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Win64; x64; Trident/7.0) ====浏览器代理====
UA-CPU: AMD64 ==处理器信息==
Accept-Encoding: gzip, deflate ==可以接受的压缩格式==
Host: 10.141.121.203:11000 ==请求的主机和端口号==
Connection: Keep-Alive ==连接保持存活==
应答头信息:
HTTP/1.1 200 OK ==响应协议版本--代码--标志====
Server: Apache-Coyote/1.1 ==服务器信息===
Content-Type: text/html;charset=UTF-8 ==包含内容类型==
Transfer-Encoding: chunked ==编码==
Date: Fri, 31 Oct 2014 14:36:22 GMT ==响应时间==
1 import java.io.*; 2 import java.net.*; 3 4 5 public class MyIe { 6 public static void main(String[] args) { 7 8 //客户端套接字 9 Socket s = null; 10 11 //输入输出流 12 InputStream is = null; 13 OutputStream os = null; 14 15 //实例化 16 try{ 17 s = new Socket("localhost",80); 18 is = s.getInputStream(); 19 os = s.getOutputStream(); 20 }catch (UnknownHostException e){ 21 System.out.println("主机未找到异常!"+e.toString()); 22 }catch(IOException e){ 23 System.out.println("IO异常"+e.toString()); 24 } 25 26 27 //向服务器端发送请求头信息 28 try{ 29 os.write("GET /upload/my.html HTTP/1.1".getBytes()); 30 os.write("Accept: */*".getBytes()); 31 os.write("Accept-Language: zh-CN".getBytes()); 32 os.write("User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Win64; x64; Trident/7.0)".getBytes()); 33 os.write("UA-CPU: AMD64".getBytes()); 34 os.write("Accept-Encoding: gzip, deflate".getBytes()); 35 os.write("Host: 10.141.121.203:80".getBytes()); 36 os.write("Connection: Keep-Alive".getBytes()); 37 38 //换行作为结束 39 os.write("\r\n".getBytes()); 40 os.write("\r\n".getBytes()); 41 }catch(IOException e){ 42 System.out.println(e.toString()); 43 } 44 45 46 //读取服务端反馈 47 byte b[] = new byte[1024]; 48 49 int len = 0; 50 51 try{ 52 while((len = is.read(b))!=-1){ 53 System.out.println(new String(b,0,len)); 54 } 55 }catch(IOException e){ 56 System.out.println("读取异常"+e.toString()); 57 } 58 try { 59 s.close(); 60 } catch (IOException e) { 61 // TODO Auto-generated catch block 62 e.printStackTrace(); 63 } 64 } 65 }
第六讲:网络编程(自定义浏览器-Tomcat服务端)
一,自定义客户端,模拟浏览器:
浏览器原理:
包装请求头信息。
向服务发送请求。
获取服务端反馈信息。
解析html,xml,javascript代码。
1 import java.io.*; 2 import java.net.*; 3 4 5 //自定义浏览器,输出服务端反馈信息 6 public class MyIe2 { 7 public static void main(String[] args) { 8 9 //客户端套接字 10 Socket s = null; 11 12 //获取输入流 13 InputStream is = null; 14 15 //获取输出流 16 OutputStream os = null; 17 18 19 //实例化对象 20 try{ 21 s = new Socket("localhost",80); 22 23 is = s.getInputStream(); 24 25 os = s.getOutputStream(); 26 }catch(UnknownHostException e){ 27 System.out.println("主机未找到"+e.toString()); 28 }catch(IOException e){ 29 System.out.println("连接异常"+e.toString()); 30 } 31 32 //提高操作效率 33 PrintStream ps = new PrintStream(os); 34 35 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 36 37 38 //向服务端发送头信息 39 ps.println("GET / HTTP/1.1"); 40 ps.println("Accept: */*"); 41 ps.println("Accept-Language: zh-CN"); 42 ps.println("User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.2; Win64; x64; Trident/7.0)"); 43 ps.println("UA-CPU: AMD64"); 44 ps.println("Accept-Encoding: gzip, deflate"); 45 ps.println("Host: 10.141.121.203:80"); 46 ps.println("Connection: closed"); 47 ps.println(); 48 49 50 //获取服务端反馈信息 51 String line = null; 52 try { 53 54 //循环读取 55 while((line = br.readLine())!=null){ 56 57 System.out.println(line); 58 } 59 } catch (IOException e) { 60 // TODO Auto-generated catch block 61 e.printStackTrace(); 62 } 63 } 64 }
第七讲,第八讲:黑马程序员_毕向东_Java基础视频教程第24天-07-网络编程(自定义图形界面浏览器-Tomcat服务端)第24天-08-网络编程(URL-URLConnection)
一,URL和URLConnection 了解:
- URL 类的了解:
- 类的定义:public final class URLextends Object implements Serializable 类
URL
代表一个统一资源定位符,它是指向互联网“资源”的指针。 - 构造方法:public URL(String spec) throws MalformedURLException 根据
String
表示形式创建URL
对象。 - 构造方法:public URL(String protocol, String host,int port, String file) throws MalformedURLException 根据指定
protocol
、host
、port
号和file
创建URL
对象。 - 方法:public final Object getContent() throws IOException 获取此 URL 的内容。==相当于:openConnection().getContent()==
- 方法:public String getPath() 获取此
URL
的路径部分。 - 方法:public String getHost() 获取此
URL
的主机名(如果适用)。 - 方法:public int getPort() 获取此
URL
的端口号。===注:一般输入网址,是不带端口号的,此时可进行获取,通过获取网址返回的port,若port为-1,则分配一个默认的80端口=== - 方法:public String getProtocol() 获取此
URL
的协议名称。 - 方法:public String getQuery() 获取此
URL
的查询部分。 - 方法:public URLConnection openConnection() throws IOException 返回一个
URLConnection
对象,它表示到URL
所引用的远程对象的连接。
- 类的定义:public final class URLextends Object implements Serializable 类
- URLConnection 类:
- 类的定义:public abstract class URLConnection extends Object 应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源
- 构造方法私有化。===通过URL 的 openConnection() 方法获得===
- 方法:public abstract void connect() throws IOException 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。
- 方法:public void setConnectTimeout(int timeout) 设置一个指定的超时值(以毫秒为单位),该值将在打开到此 URLConnection 引用的资源的通信链接时使用。如果在建立连接之前超时期满,则会引发一个 java.net.SocketTimeoutException。超时时间为零表示无穷大超时。
- 方法:public Object getContent() throws IOException 获取此 URL 连接的内容。
- 方法:public InputStream getInputStream() throws IOException 返回从此打开的连接读取的输入流。在读取返回的输入流时,如果在数据可供读取之前达到读入超时时间,则会抛出 SocketTimeoutException。
- 方法:public OutputStream getOutputStream() throws IOException 返回写入到此连接的输出流。
- URL 类的了解:
====URI 和 URL 的区别:URI:范围更大,条形码也包含于此范围 URL:范围较小,即域名====
二,代码练习:
1 import java.io.*; 2 import java.net.*; 3 public class URLDemo { 4 public static void main(String[] args) throws IOException { 5 6 //创建URL对象 7 URL url = null; 8 9 //连接对象 10 URLConnection urlc = null; 11 12 //输入流 13 InputStream is = null; 14 15 //实例化 16 try { 17 url = new URL("Http://localhost:80/upload/my.html"); 18 urlc = url.openConnection(); 19 urlc.setDoOutput(true); 20 urlc.setDoInput(true); 21 is = urlc.getInputStream(); 22 23 } catch (MalformedURLException e) { 24 System.out.println("格式错误"+e.toString()); 25 }catch(IOException e){ 26 System.out.println("连接异常"+e.toString()); 27 } 28 29 30 //自护缓冲流提高效率,读入服务端反馈 31 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 32 String line = null; 33 34 //输出 ===注意此处没有Http响应头,因为此时是用的应用层=== 35 while((line = br.readLine())!=null){ 36 System.out.println(line); 37 } 38 39 } 40 }
第九讲,第十讲:网络编程(小知识点),网络编程(域名解析)
一,Socket 有一个无参数的构造方法: public Socket(),其构造的对象可以使用 public void connect (SocketAddress endpoint) throws IOException 方法连接。
二,SocketAddress 类:
- 此类是一个抽象类,其子类InetSocketAddress 实现了IP套接字地址(IP地址+端口号)。
- 使用它可以更加方便的进行网络连接。
三,ServerSocket 类:
- 构造方法:public ServerSocket(int port, int backlog) throws IOException 利用指定的 backlog(同时在线人数) 创建服务器套接字并将其绑定到指定的本地端口号。
四,在浏览器输入网址输入地址访问网站流程:
- 先到C:\Windows\System32\drivers\etc\hosts 文件中进行查找,若有对应主机的映射关系,则进行访问。
- 到域名解析服务器中进行查找。
- 访问主机。
- host应用:可屏蔽一些恶意网址,即将对应的映射关系写入hosts中,将IP地址改为本机的回环地址,那么会直接找到hosts,就不会将请求发送出去了。