Java基础—网络编程(二)
来源:互联网 发布:网络机顶盒哪个好用 编辑:程序博客网 时间:2024/06/05 05:22
- 一TCP协议通信
- 二URL类
- 三URLConnection类
- 四扩展知识
- 五域名解析
一、TCP协议通信
- 1.上传图片练习
- 1)将图片上传到服务器端保存。
示例代码:
package com.heisejiuhuche.socket;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.net.Socket;public class PicUploadClient { public static void main(String[] args) throws Exception { upload(); } private static void upload() throws Exception { /* 创建Socket对象,指定主机和端口 */ Socket s = new Socket("localhost", 10007); /* 创建File对象,关联文件 */ File file = new File("C://Users//jeremy//Documents//javaTmp//me.jpg"); /* 创建输入输出流对象 */ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); int b = 0; /* 上传文件 */ while((b = bis.read()) != -1) { bos.write(b); bos.flush(); } /* 发送结束符 */ s.shutdownOutput(); /* 获取反馈信息 */ InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int msg = in.read(buf); System.out.println(new String(buf, 0, msg)); bis.close(); s.close(); }}package com.heisejiuhuche.socket;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class PicUploadServer { public static void main(String[] args) throws Exception { recv(); } private static void recv() throws Exception { ServerSocket ss = new ServerSocket(10007); Socket s = ss.accept(); /* 创建输入输出流对象 */ BufferedInputStream bis = new BufferedInputStream(s.getInputStream()); File file = new File("C://Users//jeremy//Documents//me.jpg"); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); int b = 0; /* 保存文件 */ while((b = bis.read()) != -1) { bos.write(b); bos.flush(); } /*发送反馈信息 */ OutputStream out = s.getOutputStream(); out.write("上传成功".getBytes()); bos.close(); s.close(); ss.close(); }}
程序运行结果:上传成功
- 2)TCP客户端并发上传图片
- 这个服务端有局限性。当一个客户端连接服务器之后,因为服务器是单线程,那么其他客户端如果想连接服务器,只能带前一个客户完成所有任务,才能连接。要同时处理多个客户端请求,应该明确客户端要在服务器端要执行的代码,然后将每个客户端封装到一个线程当中,同步执行。
示例代码:
package com.heisejiuhuche.socket;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.net.Socket;public class UploadPicByThreadClient { public static void main(String[] args) throws Exception { /* 限制文件格式,大小等条件 */ if(args.length != 1) { System.out.println("请指定一个jpg文件上传..."); 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对象,指定主机和端口 */ Socket s = new Socket("localhost", 10007); /* 创建File对象,关联文件 */// File file = new File("C://Users//jeremy//Documents//javaTmp//me.jpg"); /* 创建输入输出流对象 */ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); int b = 0; /* 上传文件 */ while((b = bis.read()) != -1) { bos.write(b); bos.flush(); } /* 发送结束符 */ s.shutdownOutput(); /* 获取反馈信息 */ InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int msg = in.read(buf); System.out.println(new String(buf, 0, msg)); bis.close(); s.close(); }}package com.heisejiuhuche.socket;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class UploadPicByThreadServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10007); while(true) { Socket s = ss.accept(); new Thread(new PicServerThread(s)).start(); } }}/* 将客户端上传的代码封装成线程 */class PicServerThread implements Runnable { private Socket s; PicServerThread(Socket s) { this.s = s; } public void run() { String ip = s.getInetAddress().getHostAddress(); int count = 1; try { System.out.println(ip + " connected.."); /* 避免文件名重复 */ File file = new File("C://Users//jeremy//Documents//" + ip + "(" + count + ")" + ".jpg"); /* 循环判断,如果文件存在,让count自增 */ while(file.exists()) file = new File("C://Users//jeremy//Documents//" + ip + "(" + count++ + ")" + ".jpg"); /* 读取文件,写入服务端 */ BufferedInputStream bis = new BufferedInputStream(s.getInputStream()); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); int b = 0; while((b = bis.read()) != -1) { bos.write(b); bos.flush(); } OutputStream out = s.getOutputStream(); out.write("上传成功".getBytes()); bos.close(); s.close(); } catch(IOException e) { throw new RuntimeException(ip + " 上传失败..."); } }}
- 2.检测用户名练习
- 客户端通过键盘录入用户名,如果该用户存在,在服务器端显示xxx,已登录;在客户端显示xxx,欢迎光临。如果用户不存在,在服务端显示xxx,尝试登录;在客户端显示xxx,该用户不存在。
示例代码:
package com.heisejiuhuche.socket;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 s = new Socket("localhost", 10009); BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); for(int x = 0; x < 3; x++) { String line = bufr.readLine(); /* 如果输入为空,直接结束循环 */ if(line == null) break; /* 发送名字到服务器端 */ pw.println(line); /* 读取回馈信息 */ String feedback = bufIn.readLine(); System.out.println(feedback); /* 如果回馈信息有欢迎字样,结束循环 */ if(feedback.contains("欢迎")) break; } bufr.close(); s.close(); }}package com.heisejiuhuche.socket;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class LoginServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(10009); while(true) { Socket s = ss.accept(); new Thread(new UserThread(s)).start(); } }}class UserThread implements Runnable { private Socket s; UserThread(Socket s) { this.s = s; } public void run() { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + " connected..."); try { for(int x = 0; x < 3; x++) { BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String name = bufIn.readLine(); if(name == null) break; /* 这一行代码一定放在for循环里面,不然readLine的指针回不到文件开端,读不到名字 */ BufferedReader bufr = new BufferedReader(new FileReader("C://Users//jeremy//Documents//javaTmp//user.txt")); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); String line = null; Boolean flag = false; /* 根据flag的结果判断要进行的操作 */ while((line = bufr.readLine()) != null) { if(name.equals(line)) { flag = true; break; } } if(flag) { System.out.println(name + "已登录!"); pw.println(name + ", 欢迎登录!"); break; } else { System.out.println(ip + "正在尝试登录..."); pw.println(name + "不存在..."); } bufr.close(); } s.close(); } catch(IOException e) { throw new RuntimeException(ip + "校验失败..."); } }}
- 3.自定义浏览器
- 1)HTTP请求消息头
- 请求头信息中包括了发送该请求的主机地址,端口,路径,可以接受的应用程序类型,所使用语言,封装压缩形式等信息。请求头信息示例如下:
GET / HTTP/1.1Accept: text/html, application/xhtml+xml, */*Accept-Language: en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like GeckoAccept-Encoding: gzip, deflateHost: 127.0.0.1:11000DNT: 1Connection: Keep-Alive
模拟一个浏览器,想服务器发送请求头信息,获取页面。
示例代码:
package com.heisejiuhuche.socket;import java.io.InputStream;import java.io.PrintWriter;import java.net.Socket;public class BrowserClient { public static void main(String[] args) throws Exception { /* 访问本机的Tomcat服务器,端口8080 */ Socket s = new Socket("localhost", 8080); PrintWriter out = new PrintWriter(s.getOutputStream(), true); /* 发送HTTP请求头 */ out.println("GET / HTTP/1.1"); out.println("Accept: */*"); out.println("Accept-Language: en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3"); out.println("Accept-Encoding: gzip, deflate"); out.println("Connection: closed"); /* 用空行分割请求头和请求体 */ out.println(); out.println(); /* 获取服务器返回的信息 */ InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf, 0, len)); s.close(); }}
二、URL类
- 1.概述
URL(Uniform Resource Locator)
类代表一个同一资源定位符。该类是指向互联网资源的指针。- 2.常用方法
- -String getFile():获取此URL的文件名
-String getHost():获取此URL的主机名
-String getPath():获取此URL的路径部分
-int getPort():获取此URL的端口号
-String getProtocol():获取此URL的协议名称
-String getQuery():获取此URL的查询部
- 3.常用方法演示
示例代码:
package com.heisejiuhuche.socket;import java.net.MalformedURLException;import java.net.URL;public class URLDemo { public static void main(String[] args) throws MalformedURLException { URL url = new URL("http://192.168.0.100:8080/myweb/index.html/?name=hsjhc&age=25"); /* 演示常用方法 */ System.out.println("getProtocol: " + url.getProtocol()); System.out.println("getHost: " + url.getHost()); System.out.println("getPort: " + url.getPort()); System.out.println("getPath: " + url.getPath()); System.out.println("getFile: " + url.getFile()); System.out.println("getQuery: " + url.getQuery()); }}
程序运行结果:
getProtocol: httpgetHost: 192.168.0.100getPort: 8080getPath: /myweb/index.html/getFile: /myweb/index.html/?name=hsjhc&age=25getQuery: name=hsjhc&age=25
注意:
没有指定端口,返回-1;开发时要进行判断,如果port的值为-1,要给port赋值为80
三、URLConnection类
- 1.概述
URLConnection
类对象是URL对象调用openConnect()
方法之后的返回值,就能得到这个URL
的连接对象,也就是目标主机对象;获取URLConnection
对象可以方便获取Socket输入流对象
。- 2.URLConnection类演示
示例代码:
package com.heisejiuhuche.socket;import java.io.InputStream;import java.net.URL;import java.net.URLConnection;public class URLConnectionDemo { public static void main(String[] args) throws Exception { /* 封装URL对象 */ URL url = new URL("http://192.168.0.100:8080/myweb/indetml/?name=hsjhc&age=25"); /* 调用url对象的openConnection方法,得到URLConnection对象 */ URLConnection conn = url.openConnection(); System.out.println(conn); /* 因为URLConnection对象中封装了Socket对象 * 所以可以调用getInputStream()方法获取输入流来读取服务器端数据 */ InputStream in = conn.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf, 0, len)); }}
注意:
url.openConnection().getInputStream()这行代码,可以简写成url.openStream();该方法是URLConnection类中获取InputStream的便捷方法
四、扩展知识
- 1.Socket空参数构造函数
- 通过调用
connect()
方法连接主机;connect()
方法可以接收一个SocketAddress
对象作为参数;SocketAddress
类的子类InetSocketAddress
类封装IP地址
和端口
;那么以前在创建Socket对象
的时候分开写主机IP和端口,现在也可以调用connect
方法,传递一个InetSocketAddress
对象即可。- 2.ServerSocket类接收的backlog参数
backlog
表示队列的最大长度。它代表能同时连接到服务器的最大客户端个数。在服务器端开发时,要指定这个参数,避免服务器因连接数过多而死机。五、域名解析
- 1.概述
IP地址
不容易记忆,通常人们在访问网站的时候,在地址栏输入的都是类似于www.baidu.com
这样的域名。但是要访问到网络上对应这个域名的那个主机,需要将这个域名解析成IP地址。这个过程,需要DNS域名解析服务器
来完成。DNS服务器
中记录的是每个域名对应的IP地址映射表。- 2.基本原理
PC在访问网站的时候,要走这4步流程。在浏览器输入域名之后,第1步,到本机C盘``(C:\windows\Systems\drivers\etc\)
下的hosts文件
,寻找这个域名是否在本地有已经配置的IP地址,如果有,直接访问该IP,否则,进入第2步;第2步,访问公网DNS服务器,找到DNS服务器上的域名——IP映射关系;第3步,DNS服务器将对应的IP地址返回给PC;第4步,PC端访问该IP地址,找到公网上的指定主机。
注意:
127.0.0.1与localhost之间的映射关系在本机上C盘下的hosts文件中。该文件可以用于屏蔽恶意网站。
0 0
- Java基础—网络编程(二)
- Java基础-网络编程(二)
- Java基础——网络编程(二)
- java基础整理二十四(网络编程二)
- 网络编程基础(二)
- java基础整理二十三(网络编程)
- 网络编程基础<二>
- Java——网络编程(二)
- Java基础—网络编程(一)
- Java基础—网络编程(一)
- Java 网络编程(二)
- Java网络编程(二)
- java网络编程(二)
- Java基础—网络编程
- Java基础(网络编程)
- Java笔记二十三.网络编程基础与UDP编程
- 网络编程基础(二)——使用UDP
- Linux——网络编程基础(二)
- 只进 ResultSet 不支持请求的操作。
- 【内部排序】三:希尔排序(Shell Sort)的多种实现(不断优化+源码)
- Android 实现视频录制播放
- 合肥app开发公司哪家好
- linux的apk重签名脚本
- Java基础—网络编程(二)
- js实现的倒计时操作
- LinkedList笔记
- 5.1 Brackets
- 小谈Online-game服务器端设计(1、2)
- 利用mybatis-gernerator插件生成mybatis 所需文件
- AFNetworking的网络状态监听
- usb 学习笔记
- 合肥软件开发外包公司有哪些