一. 计算机网络介绍
1. 计算机网络介绍:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
2. 计算机网络分类:虽然网络类型的划分标准各种各样,但从地理位置划分是一种大家都认可的网络划分标准,按这种标准可以把网络类型分为局域网,城域网,广域网三种
(1) 局域网:一般来说只能是一个较小的区域内
(2) 城域网:是不同地区的网络互联,不过在此要说明的一点就是这里的网络划分并没有严格意义上的地理范围上的区分,只能是一个定性的概念
(3) 广域网:所覆盖范围比城域网(MAN)更广,它一般是在不同城市之间的LAN或者MAN网络互联,地理范围可以从几百里到几千公里,Internet就是一种广域网
3. 网络类型模型
(1) 四层划分法:
<1>应用层 ;<2>传输层
<3>互联网层 ;<4>网络接口层
(2) 五层分法:又将网络接口层细分为:<1>数据链路层;<2>物理层
(3)七层分法:将应用层细分为:<1>应用层;<2>表示层;<3>会话层
二.TCP协议
1. TCP/IP协议不是TCP和IP这两个协议的合称,而是指因特网整个TCP/IP协议族
2.在TCP/IP协议中,最重要的协议是TCP,UDP,IP协议
3.TCP协议:
(1)TCP协议是基于面向连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠地连接
注:TCP协议在建立连接需要三次回话(握手)
A——>B;B——A;A——B;
(2)特点:<1>面向连接;<2>安全,可靠;
<3>效率相对较低;<4>数据大小无限制
4. UDP协议:
(1) UDP协议是一种面向无连接的通讯协议UDP数据包括端口号和源端口号信息,由于通讯不需要连接,所以不需要连接,所以可以实现广播发送
(2) UDP通讯是不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编码验证
(3) 特点:<1>无连接;<2>可靠性不高;<3>效率高;<4>每次最大传输64kb
5. IP协议:
(1) IP的责任就是把数据从源传送到目的地,负责保证传送的可靠性,控制流,包顺序和其他对于主机到主机协议来说很普通的服务
(2) IP协议中还有一个非常重要的内容,那就是给因特网上的每台计算机和其他设备都规定了一个唯一的地址,叫做“IP地址”
6.IP地址:就是给每个连接在互联网上的主机分配的一个32位地址(IP地址就好像是电话号码:有了某人的电话号码,你就能与他进行通讯,同样有了某台主机的IP地址,就能你这台主机进行通讯了)
(1)IP地址的组成:IP地址=网络地址+主机地址
<1>网络地址:标识计算机或网络设备所在的网段
<2>主机地址:标识特定主机或网络设备
注:0.0.0.0:本机
127.0.0.1:本机回环地址,用于本机测试
255.255.255.255:当前子网,一般用于向当前子网广播信息
(2)IP地址的配置和检测
<1>查看本机IP地址:ipconfig
<2>测试网络是:ping目标IP地址
6. 端口号:具有网络功能的应用软件标识号
(1) 端口是一个软件结构,被客户程序或服务程序用来发送和接收数据,一台服务器有256*256个端口
(2) 0-1023是公认的端口号,即已经公认定义或将要公认定义的软件保留的
(3) 1024-65535是没有公共定义的端口号,用户可以自己定义这些端口的作用
(4) 端口与协议有关:TCP和UDP的端口互不相干
二. Scoket(套接字)
1. 两个应用程序可以通过一个双向的网络通信连接实现数据交换,这个双 向链接的一端称为一个Scoket
2. Scoket可以看成两个程序进行通讯连接 中的一个端点,一个程序将一个 信息写入Scoket中,该Scoket将这段信息发送给另外一个Scoket中, 使这段信息能传送到其他程序中
3. Scoket通常用来实现client-server(客户端—服务端)连接,建立连接时 所需要的寻址信息为远程计算机的IP地址和端口号(Port Number)
4. 网络编程的四个基本步骤
(1)创建scoket;
(2)打开连接到scoket的输入输出流/输出流(通过Scoket的 getInputStream()和getOutputStream());
(3)按照一定的协议对scoket进行读写/写操作;
(4)关闭scoket;
5. 基于TCP协议的Scoket编程
(1)基于TCP协议的scoket的网络通信
<1>用来实现双向安全连接网络通信
<2>TCP Scoket通常用来实现client-server连接,建立连接时所 需要的寻址信息为远程计算机的IP地址和端口号(Port Number)
(2) TCP Scoket通信模型:进行网络通信时,Socket需要借助数据流来完成数据的传递工作
6.TCP通信原理
例1. (实现服务端与客户端连接)
建立服务端:
package scoket; import java.io.*; import java.net.*; public class Server { /* 编写服务器 */ public static void main(String[] args) { ServerSocket server=null; Socket socket=null; OutputStream out=null; try { server=new ServerSocket(9999);//创建服务器,并规定端口号为9999 System.out.println("等待服务器连接.."); socket=server.accept();//监听服务器连接,连接之前一直阻塞 out=socket.getOutputStream();//获取Socket输出流,用来与他连接的服务器写入 out.write("你好,Socket编程!!!".getBytes());//向输出流中写入内容,用getBytes()转化为字节数组 System.out.println("发送成功..."); } catch (IOException e) { e.printStackTrace(); }finally{ try { server.close();//关闭服务器 socket.close();//关闭socket } catch (IOException e) { e.printStackTrace(); } } } }
建立客户端:
package scoket; import java.io.*; import java.net.*; /* * 编写客户端 */ public class Client { public static void main(String[] args){ Socket socket=null; InputStream input=null; try { socket=new Socket("localhost",9999);//连接到服务器,localhost本机 input=socket.getInputStream();//获取socket输入流,用于获取服务器发送的信息 byte[] b=new byte[1024];//建立字节数组缓冲区 int len=input.read(b);//读取字节数组 System.out.println("获取到的服务器信息为:"+new String(b,0,len));//将获取到的信息转化为字符串 } catch (Exception e) { e.printStackTrace(); } } }
运行结果为(运行时先启动服务端再启动客户端):
服务端:
等待服务器连接..
发送成功...
客户端:
获取到的服务器信息为:你好,Socket编程!!!
例2(将输入输出流进行装饰):
服务端:
package decorator; import java.io.*; import java.net.*; /* * 服务端 */ public class Server { public static void main(String[] args) { ServerSocket server=null; Socket socket=null; try { server=new ServerSocket(9999);//创建服务端,并规定端口号 System.out.println("客户端开始连接..."); socket=server.accept();//监听客户端,连接之前 一直阻塞 PrintStream ps=new PrintStream(socket.getOutputStream());//获取socket输出流,并封装到PrintStream输出流中; ps.println("通过PrintStream发送信息...");//利用println()向客户端发送信息 System.out.println("服务器信息发送完毕..."); } catch (IOException e) { e.printStackTrace(); }finally{ try { server.close();//关闭服务器资源 socket.close();//关闭socket } catch (IOException e) { e.printStackTrace(); } } } }
客户端:
package decorator; import java.io.*; import java.net.*; /* * 客户端 */ public class Client { public static void main(String[] args){ Socket socket=null; InputStream input=null; try { socket=new Socket("localhost", 9999);//创建客户端 ,并建立连接 //将socket输入流封装到BufferedReader中 BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); String str=br.readLine();//利用readLine()读取接收到的服务端信息 System.out.println("客户端:"+str); } catch (Exception e) { e.printStackTrace(); } finally{ try { socket.close();//关闭socket资源 } catch (IOException e) { e.printStackTrace(); } } } }
运行结果:
客户端开始连接...
服务器信息发送完毕...
客户端:通过PrintStream发送信息...
例2. (模仿反响机制echo)
服务端线程类:
package echo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; /* * 服务端线程类 */ public class ECHORunnable implements Runnable{ private Socket socket; public ECHORunnable(Socket socket) { this.socket = socket; } @Override public void run() { try { //获取输入流,用于读取客户端信息,用BufferedReader包装 BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); //获取输出流用于向客户端发送信息,用PrintStream包装 PrintStream ps=new PrintStream(socket.getOutputStream()); //与客户端不断交互,直到客户端说‘bye’时退出与客户端交互 while(true){ String str=br.readLine();//读取客户端发送来胡信息 ps.println(str); if(str.equals("bye")){ socket.close(); break; } } } catch (IOException e) { e.printStackTrace(); } } }
服务端:
package echo; /* * 服务端 */ import java.io.IOException; import java.net.*; public class Server { public static void main(String[] args) { ServerSocket server=null; Socket socket=null; try { server=new ServerSocket(9999);//创建服务端并规定端口号为9999 boolean flag=true; int count=0; while(flag){ count++; System.out.println("服务器与第"+count+"位客户端连接....."); socket=server.accept();//监听客户端连接 new Thread(new ECHORunnable(socket)).start();//开启服务端线程 } } catch (IOException e) { e.printStackTrace(); } } }
客户端:
package echo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.net.UnknownHostException; /* * 客户端 */ public class Client { public static void main(String[] args) { BufferedReader keybr=new BufferedReader(new InputStreamReader(System.in)); Socket socket=null; try { socket=new Socket("localhost",9999);//连接本地服务端 PrintStream ps=new PrintStream(socket.getOutputStream());//获取输出流,用于向客户端发送信息 BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));//获取输入流用于读取服务端返回胡信息 while(true){ System.out.println("白雪公主:"); String revice=keybr.readLine();//读取键盘输入 ps.println(revice);//发送客户端信息 String str=br.readLine();//获取服务端信息 System.out.println("青蛙王子:"+str); if("bye".equals(revice)){ socket.close(); break; } } } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
白雪公主:
你好
青蛙王子:你好
白雪公主:
你在干啥
青蛙王子:你在干啥
白雪公主:
bye
青蛙王子:bye
例4(C-S传图片):
服务端线程类:
package binary; import java.io.*; import java.net.Socket; // 上传线程类 public class UploadRunnable implements Runnable{ private Socket socket; public UploadRunnable(Socket socket){ this.socket=socket; } @Override public void run() { OutputStream out=null; try { InputStream input=socket.getInputStream(); // 用此来接收客户端发来的内容 String fileName=System.currentTimeMillis()+".jpg"; out=new FileOutputStream("d:"+File.separator+"upload"+File.separator+fileName); // 用来写入服务器中的输出流 byte[] b=new byte[1024]; int len=0; // 循环从客户端读,写入服务器端 while((len=input.read(b))!=-1){ out.write(b, 0, len); } System.out.println(Thread.currentThread().getName()+"写入成功!"); } catch (IOException e) { e.printStackTrace(); }finally{ try { out.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
服务端:
package binary; import java.io.IOException; import java.net.*; // 服务端 public class Server { public static void main(String[] args) { ServerSocket server=null; try { server=new ServerSocket(8888); int count=0; while(true){ count++; System.out.println("等待第"+count+"位客户连接..."); Socket socket=server.accept(); // 监听客户端连接,连接之前一直阻塞 new Thread(new UploadRunnable(socket)).start(); // 启动线程,在线程中与客户端交互 } } catch (IOException e) { e.printStackTrace(); } } }
客户端:
package binary; import java.io.*; import java.net.*; public class Client { public static void main(String[] args) { Socket socket=null; InputStream input=null; try { socket=new Socket("localhost",8888); input=new FileInputStream("d:"+File.separator+"images"+File.separator+"bingfa.jpg"); OutputStream out=socket.getOutputStream(); // 用来向服务端不断写入 byte[] b=new byte[1024]; int len=0; // 从客户端磁盘上读,不断写入服务端 while((len=input.read(b))!=-1){ out.write(b,0,len); } System.out.println("客户端上传成功!"); } catch (Exception e) { e.printStackTrace(); }finally{ try { input.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
【本次总结完毕】