第13篇-JAVA 网络编程
- 每篇一句 :比我强大的人都在努力我还有什么理由不拼命
- 初学心得: 不去追逐你所渴求,你将永远不会拥有
- (笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-22| JAVA 网络编程 ]
1.网络编程基本概念
1.什么是计算机网络
计算机网络,是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通讯协议的管理和协调下,实现资源共享和信息传递的计算机系统
把分布在不同地理区域的计算机与专门的外部设备用通讯线路互连成一个规模大
功能强的网络系统,从而使众多的计算机可以方便地相互传递信息,共享硬件,软件、数据信息等资源
2.计算机网络的主要功能
资源共享,信息传输与集中处理,均衡负荷与分布处理,综合信息服务(www/综合业务数字网络ISDN)等
3.网络通讯协议
要使计算机连成网络能够互相通信,需要对数据传输速率,传输代码,代码结构,传输控制步骤,出错
控制等制定一组标准,这一组共同遵守的通讯标准就是网络通讯协议
4.网络通讯接口
为了是这两个结点之间进行对话,必须在它们之间建立通讯工具(既接口)
使彼此之间能进行信息交换,接口包括两部分:
1.硬件装置:实现结点之间的信息传递
2.软件装置:规定双方进行通讯的约定协议
4.TCP/IP
5.程序开发结构
5.IP协议
IP协议是Internet上使用的一个关键协议,它的全称是Internet Protocol,即Internet协议,通常简称IP协议
通过使用IP协议,从而使Internet成为一个允许连接不同类型的计算机和不同操作系统的网络。
IP协议只保证计算机能发送和接收分组数据。IP协议负责将消息从一个主机传送到另一个主机,消息在传送的过程中被分割成一个个的小包
6.Java对TCP/IP协议的支持
- TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路
- 一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信
- Java对基于TCP协议的网络通信提供了良好的封装,Java使用Socket对象来代表两端的通信接口,并通过Socket产生IO流来进行网络通信
2.网络通讯协议(TCP/IP UDP)
IP的概念
IP是互联网上的每一台计算机都有得一个唯一表示自己的标记
IP地址使用4个8位的二进制数据表示,每8位之间使用圆点隔开,每个8位整数可以转换成一个0~255的十进制整数
因此一般看到的IP地址类似:192.168.1.1
IP地址分类:
- IPv4:32位,分4段,0~255之间的十进制表示
- IPv6:128位,分8段,0000~FFFF的十六进制数值,冒号分割
如:1080:0:0:0:8:800:200C:417A
- IP地址 = 网络地址 + 主机地址
- 网络号:用于识别主机所在的网络
- 主机号:用于识别该网络的主机
什么是端口?
如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口 可以有65536(即:2^16)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)
同一台机器上不能有两个程序使用同一个端口;
端口的分类:
- 公认端口:0~1023,他们紧密绑定一些服务
- 注册端口:1024~49151,松散绑定一些服务
- 动态端口:49152~65535,动态使用的端口,程序一般不会使用这些端口;
TCP协议
- TCP协议被称作一种端对端协议
- 这是因为它为两台计算机之间的连接起了重要作用:当一台计算机需要与另一台远程计算机连接时,TCP协议会让它们建立一个连接:用于发送和接收数据的虚拟链路。
- TCP协议负责收集这些信息包,并将其按适当的次序放好传送,在接收端收到后再将其正确地还原
- TCP协议保证了数据包在传送中准确无误。TCP协议使用重发机制:当一个通信实体发送一个消息给另一个通信实体后,需要收到另一个通信实体确认信息,如果没有收到另一个通信实体的确认信息,则会再次重发刚才发送的信息
- 通过这种重发机制,TCP协议向应用程序提供可靠的通信连接,使它能够自动适应网上的各种变化。即使在 Internet 暂时出现堵塞的情况下,TCP也能够保证通信的可靠
UDP协议
- UDP协议是一种不可靠的网络协议
- 它在通信实例的两端各建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送、接收数据报的对象,Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送、接收的数据报
发送端:在发送端,要在数据包对象中明确目的地IP及端口
DatagramSocket ds = new DatagramSocket();
byte[] by = “hello,udp”.getBytes();
DatagramPacket dp = new DatagramPacket(by,0,by.length,
InetAddress.getByName(“127.0.0.1”),10000);
ds.send(dp);
ds.close();
接收端:在接收端,要指定监听的端口
DatagramSocket ds = new DatagramSocket(10000);
byte[] by = new byte[1024];
DatagramPacket dp = new DatagramPacket(by,by.length);
ds.receive(dp);
String str = new String(dp.getData() );
System.out.println(str+"--"+dp.getAddress());
ds.close();
3.UDP和TCP的对比
- TCP协议:可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大
- UDP协议:不可靠,差错控制开销较小,传输大小限制在64K以下,不需要建立连接
4.QSI七层模型
物理,比特流 网卡
数据链路,数据帧 交换机
网络,IP TCP上层・数据 数据包 路由器
传输,TCP上头上层数据 数据段 防火墙
会话,
表示,
应用 上层数据 48位2进制 计算机
TCP/IP4 TCP/IP5 TCP/IP7
物理层 0,1 比特流
数据链路层
网络层 数据包封装结构
传输层
会话层建立会话关系
TCP/
ARP转为Mark地址
ICMP传输用户协议
TCP需要同步才能传输数据,安全性高/传输控制协议 三次握手 四次结束
HTTP传输协议
FTP文件传输协议
SMTP邮件传输协议
DNS将域名转化为地址
UDP效率更快,但不安全/用户数据协议
ARP将IP解析成Mark地址的过程
arp -a 为了防止欺骗,实行绑定地址
实现字节流和字符流分别实现客户端,服务器返回
5.ServerSocket和Socket
1.ServerSocket(服务端)
- ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态
- ServerSocket包含一个监听来自客户端连接请求的方法:
- Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与连客户端Socket对应的Socket,否则该方法将一直处于等待状态,线程也被阻塞
- 为了创建ServerSocket对象,ServerSocket类提供了如下几个构造器:
- ServerSocket(int port):用指定的端口port来创建一个ServerSocket
- 该端口应该是有一个有效的端口整数值:0~65535
- ServerSocket(int port,int backlog):增加一个用来改变连接队列长度的参数backlog
- ServerSocket(int port,int backlog,InetAddress localAddr):在机器存在多个 IP地址的情况下,允许通过localAddr这个参数来指定将ServerSocket绑定到指定的IP地址
- 服务端:建立服务端需要监听一个端口
ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept ();
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int num = in.read(buf);
String str = new String(buf,0,num);
System.out.println(s.getInetAddress().toString()+”:”+str);
s.close();
ss.close();
2.Socket(客户端)
- 客户端通常可使用Socket的构造器来连接到指定服务器,Socket通常可使用如下两个构造器:
- Socket(InetAddress/String remoteAddress, int port):创建连接到指定远程主机、远程端口的Socket,该构造器没有指定本地地址、本地端口,默认使用本地主机的默认IP地址,默认使用系统动态指定的IP地址
- Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, int localPort):创建连接到指定远程主机、远程端口的Socket,并指定本地IP地址和本地端口号,适用于本地主机有多个IP地址的情形
- 客户端:通过Socket建立对象并指定要连接的服务端主机以及端口
Socket s = new Socket(“192.168.1.1”,9999);
OutputStream out = s.getOutputStream();
out.write(“hello”.getBytes());
s.close();
6.网络通信
- 当客户端、服务器端产生了对应的Socket之后,程序无需再区分服务器、客户端,而是通过各自的Socket进行通信,Socket提供如下两个方法来获取输入流和输出流:
- InputStream getInputStream():返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据
- OutputStream getOutputStream():返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据
7.网络HTTP互联实例
实例一:下载网络图片保存到此项目目录
package cn.http;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class HttpPhoto {
@SuppressWarnings("resource")
public static void main(String[] args) {
//打开url网址
String url = "http://t1.27270.com/uploads/150609/7-1506091506401R.jpg";
try {
URL uu = new URL(url);//创建URL对象
URLConnection uc = uu.openConnection();//返回URLConnection
uc.connect();//发起请求连接
InputStream in = uc.getInputStream();//输入
byte[] bytes = new byte[1024];//字节储存
int len = 0;
File f = new File("美女图片.jpg");//将图片保存跟目录
FileOutputStream fos = new FileOutputStream(f);//输出
//循环读取
while((len = in.read(bytes))!=-1){
fos.write(bytes,0,len);
}
System.out.println("图片下载成功!");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
实例二:与网络机器人聊天功能
package cn.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;
/**
* 连接接口实现聊天功能
* JSON数据格式
* @author JEEP-711
*/
public class HttpCalling {
@SuppressWarnings({ "unused", "resource" })
public static void main(String[] args) {
String name = "咨询助理";
Scanner sc = new Scanner(System.in);//接收进控制键盘输入
System.out.println("Hi,现在我们已经是好友啦,开始我们的聊天吧!");//提示
//循环输入
while(true){
System.out.println("请输入...");//提示
String user = sc.next();//用户输入内容
//打开url接口网址
String url = "http://www.tuling123.com/openapi/api?key=4c767f02ca7b44378156821ab35856df&info="+user;
try {
URL uu = new URL(url);//创建URL对象
URLConnection uc = uu.openConnection();//返回URLConnection
uc.connect();//发起请求连接
//读取原文件
BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
StringBuffer sb = new StringBuffer();
String s = "";
s = br.readLine();
String[] str = s.split(":");//分隔字符串
String[] strs = str[2].split("\"");
//for数组
for(String sr : strs){
System.out.println(name +"发来消息:"+strs[1]);
}
//JSONObject jc = new JSONObject(s);
//System.out.println(name +"发来消息:"+br.readLine());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
实例三:网络编程传输文件
package cn.socket;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务端
* @author JEEP-711
*
*/
public class Servers extends ServerSocket{
private static final int PORT = 8000;//定义静态整形常量端口号
private ServerSocket ss;//定义服务端
private Socket sk;//定义客户端
private DataInputStream d;//定义
private FileOutputStream fp;//定义文件传输
//定义构造方法并抛出异常
public Servers()throws Exception{
try {
try {
ss = new ServerSocket(PORT);//传值-端口号
while(true){
sk = ss.accept();
d = new DataInputStream(sk.getInputStream());
//文件名和长度
String fileName = d.readUTF();
long fileLeng = d.readLong();
fp =new FileOutputStream(new File("src\\" + fileName));
byte[] bytes = new byte[1024];//定义为1024个字节
int len = 0;//定义为0
//文件传输提示
System.out.println("----正在开始接收文件<" + fileName +"&,文件大小为<" + fileLeng +"&----");
while(true){
int read =0;
read = d.read(bytes);
if(read == -1)
break;
len += read;
System.out.println("接收文件进度" +100 * len/fileLeng +"%...");//文件接收提示
fp.write(bytes,0, read);//
fp.flush();//刷新
}
System.out.println("----接收文件<" + fileName +"&成功-------");
sk.close();//关闭流客户端
}
}catch (Exception e) {
e.printStackTrace();
//统一出口
}finally {
//如果传输不等于空
if(d !=null)
d.close();//则关闭传输流
//如果文件传输不等于空
if(fp !=null)
fp.close();//则关闭传输文件流
ss.close();//关闭服务器流
}
}catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception{
new Servers();//调用Servers方法
}
}
package cn.socket;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.Socket;
/**
* 客户端
* @author JEEP-711
*
*/
public class Cilens extends Socket{
private static final String server_ip = "192.168.199.109";//定义静态字符串常量IP地址
private static final int duankou = 8000;//定义静态整形常量端口号
private Socket s;//定义服务器
private FileInputStream f;//定义文件
private DataOutputStream d;//定义传输
//构造方法
public Cilens(){
try {
try {
s = new Socket(server_ip,duankou);//传参数
//向服务端传送文件
File file =new File("src\\test.doc");//文件在src目录下
f = new FileInputStream(file);//传文件
d = new DataOutputStream(s.getOutputStream());
//文件名和长度
d.writeUTF(file.getName());//文件名称
d.flush();//刷新
d.writeLong(file.length());//文件长度
d.flush();//传输刷新
//传输文件
byte[] Bytes =new byte[1024];//定义byte1024的字节
int len = 0;//定义len为0
//循环
while((len = f.read(Bytes,0,Bytes.length)) &0){
d.write(Bytes,0, len);//字节从0到len
d.flush();//传输刷新
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//如果文件不等于空
if(f !=null)
f.close();//则关闭流
//如果传输不等于空
if(d !=null)
d.close();//则关闭流
s.close();//关闭流
}
}catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
new Cilens();//调用方法
}
}
初学(JAVA 网络编程 高级阶段) 难点: ★★★★★
希望每一篇文章都能够对读者们提供帮助与提升,这乃是每一位笔者的初衷
感谢您的阅读 欢迎您的留言与建议
- FaceBook:JEEP SevenEleven
- Twitter:@JEEP7ll
- 新浪官方微博: @JEEP-711
- Github博客: <https://github.com/jeep711/jeep711.github.io>
- Blog Garden:<http://www.cnblogs.com/JEEP711/>
- W3C/Blog:<http://www.w3cschool.cn/jeep711blog/>
- CSDN/Blog:<http://blog.csdn.net/jeep911>
- 51CTO/Blog:<http://jeep711.blog.51cto.com/>
- 码云:<http://git.oschina.net/JEEP711/jeep711.github.io>
- 邮箱: <jeep711@qq.com>,<JEEP-711@outlook.com>