网络编程
1.什么是网络?
概述:
将地理位置不同的,具有独立功能的多态计算机及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通讯协议的管理和协调下实现资源共享和信息传递的计算机系统
关键词:
1.独立的多台计算机
2.实现资源共享和信息传递
2.什么是网络编程?
概述:
用来实现网络互连的不同计算机上运行的程序间可以进行数据交换
3.网络模型
概述:
计算机之间以何种规则进行通信,就是网络模型研究的问题
常见模型:
OSI参考模型
TCP/IP参考模型
4.网络通讯三要素
为甚要学网络通信三要素?
因为我们需要知道计算机与计算机之间是如何我找到对方的,然后发送数据和接收数据时不会出现QQ发送的消息被微信接收到了。
举例:赵童和网恋女友奔现
赵童和网恋女友见面了
1.首先赵童要找到网恋女友
网络中,计算机要找到另一台计算机,需要通过:IP地址-计算机在网络中的唯一标识
2.赵童见到网恋女友,他们两个开始聊天,对着耳朵说
计算机和计算机之间的应用进行数据交互不会发生错误,是因为每一个网络应用程序都会对应一个或多个标记,这个标记对应就是端口号。
3.赵童和网恋女友聊天,说标准陕西话,女友说闽南话,因为互相听不懂,所以见面约定,都说普通话
计算机与计算机之间通信,也需要制定协议,建立通信后,按协议传输数据。
网络三要素:
1.IP地址
2.端口号
3.协议
4.1IP地址
如果想让计算机能在网络中进行通信,则必须给计算机指定一个唯一标识,通过这个标识号可以指定接收数据的计算机和识别发送数据的计算机。在TCP/IP协议中,这个标识号就是IP地址
所以:IP地址-计算机在网络中的唯一标识
思考:
计算机识别二进制数据,但我们IP并不是二进制,为什么?
IP:192.168.0.153表示方法:点分十进制
换算地址:11000000.10101000.00000000.10011001
4.1.1IP地址组成:网络号段+主机号段
4.1.2IP地址分类
A类:第一位为网络号段,后三位为主机号段,适用于大量主机而局域网络较少的大型网络,目前国内基本见不到
10.x.x.x是私有地址(局域网)
**B类:**前两位为网络号段,后两位为主机号段,(校园网常见)
**C类:**前三段网络号段,后一个主机号段,常用的,192.168.x.x是私有地址(也可以是局域网)
4.1.3IP类InetAddress
package org.wdit.net编程;
import java.net.InetAddress;
import java.net.UnknownHostException;
/*IP地址类
* 没构造方法
* 回环地址:127.0.0.1*/
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
InetAddress ip = InetAddress.getByName("localhost");
String address=ip.getHostAddress();
System.out.println("本机地址:"+address);
String hostName=ip.getHostName();
System.out.println("主机名:"+hostName);
}
}
4.2端口
分类
1.物理端口:就是网卡口
2.逻辑端口:就是我们网络三要素中所说的端口
A:每个网络程序至少都会有一个逻辑端口
B:用于标识进程的逻辑地址,不同进程的标识
3.有效端口:0-65535,其中0-1024系统使用或者保留端口。
4.3协议
**概述:**网络通信规则
**分类:**TCP和UDP
UDP:
将数据源和目的地封装到数据包中,不需要建立连接,每个数据包大小限制在64k;无需建立连接,是不可靠协议,传输速度快
特点:
1.数据打包
2.包大小:64k
3.不建立连接
4.速度快
5.不可靠
TCP:
建立连接,形成传输数据的通道;在连接中进行大量数据传输,通过三次握手完成连接,是可靠协议,必须建立连接,所以效率稍低。
特点:
1.建立连接通道
2.数据量没有限制
3.速度慢
4.可靠
5.Socket套接字
概述:
网络上具有唯一标识的IP地址和端口号组合才能构成唯一识别的标识的套接字
组成:
IP地址和端口号
6.UDP协议发送数据和接收数据
/*UDP接收数据
* 1.创建Socket对象(DatagramSocket)
* 2.创建数据包
* 3.调用接收
* 4.解析数据包,显示
* 5,释放资源*/
public class UDPReceiveDemo {
public static void main(String[] args) throws IOException {
DatagramSocket socket=new DatagramSocket(6666);
byte[] bytes=new byte[1024];
DatagramPacket packet=new DatagramPacket(bytes,bytes.length);
socket.receive(packet);
byte[]bytes2=packet.getData();
int len2=packet.getLength();
String info=new String(bytes2,0,len2);
System.out.println(packet.getAddress().getHostAddress()+"-"+info);
socket.close();
}
}
/*UDP发送数据
* 1.创建Socket对象(DatagramSocket)
* 2.创建数据,打包
* 3.发送方法
* 4,释放资源*/
public class UDPSendDemo {
public static void main(String[] args) throws IOException {
//创建Socket对象(DatagramSocket)
DatagramSocket socket=new DatagramSocket();
//创建数据打包
byte[] bytes = "协议发送数据".getBytes();
int len=bytes.length;
InetAddress ip=InetAddress.getByName("Java");
int port=6666;
//打包
DatagramPacket packet=new DatagramPacket(bytes,len,ip,port);
socket.send(packet);
//释放资源
socket.close();
}
}
6.1键盘录入练习到520停止发送不接收
public class UDPSendDemo {
public static void main(String[] args) throws IOException {
//创建Socket对象(DatagramSocket)
DatagramSocket socket=new DatagramSocket();
/* //创建数据打包
byte[] bytes = "协议发送数据".getBytes();
int len=bytes.length;
InetAddress ip=InetAddress.getByName("Java");
int port=6666;
//打包
DatagramPacket packet=new DatagramPacket(bytes,len,ip,port);
socket.send(packet);*/
//将发送的数据修改成键盘录入
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=br.readLine())!=null){
if("520".equals(line)){
break;
}
byte[]bytes=line.getBytes();
DatagramPacket dp=new DatagramPacket(bytes,bytes.length,InetAddress.getByName("192.168.102"),6666);
socket.send(dp);
}
//释放资源
socket.close();
}
}
public class UDPReceiveDemo {
public static void main(String[] args) throws IOException {
DatagramSocket socket=new DatagramSocket(6666);
while (true) {
//创建数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//调用接收
socket.receive(packet);
//解析显示
byte[] bytes2 = packet.getData();
int len2 = packet.getLength();
String info = new String(bytes2, 0, len2);
System.out.println(packet.getAddress().getHostAddress() + "-" + info);
}
}
}
6.2聊天模拟案例
发送端:
public class SendThread implements Runnable {
private DatagramSocket ds;
public SendThread(DatagramSocket ds){
this.ds=ds;
}
@Override
public void run() {
try{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=br.readLine())!=null){
if("520".equals(line)){
break;
}
byte[]bytes=line.getBytes();
DatagramPacket dp=new DatagramPacket(bytes,bytes.length, InetAddress.getByName("192.168.102"),6666);
ds.send(dp);
}
//释放资源
ds.close();}catch(IOException e){
e.printStackTrace();
}
}
}
接收端:
public class ReceviceThread implements Runnable {
private DatagramSocket ds;
public ReceviceThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try{
while (true) {
//创建数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//调用接收
ds.receive(packet);
//解析显示
byte[] bytes2 = packet.getData();
int len2 = packet.getLength();
String info = new String(bytes2, 0, len2);
System.out.println(packet.getAddress().getHostAddress() + "-" + info);
}}catch(IOException e){
e.printStackTrace();
}
}
}
测试端:
public class ChatDemo {
public static void main(String[] args) throws SocketException {
DatagramSocket sendDs=new DatagramSocket();
DatagramSocket receciveDs=new DatagramSocket(6666);
//发送端和接收端的线程类
SendThread st=new SendThread(sendDs);
ReceviceThread rt=new ReceviceThread(receciveDs);
Thread t1=new Thread(st);
Thread t2=new Thread(rt);
t1.start();
t2.start();
}
}
7.TCP传输
1.前提:
1.Socket和ServerSocket
2.建立客户端和服务器端
3.建立连接后,通过Socket中的IO流进行数据的传输
4.关闭Socket
5.这里的客户端和服务器端是两个独立的程序
2.TCP发送端传输步骤:
1.建立客户端的Socket服务,明确要连接的服务器。
2.如果连接建立成功,就表明已经建立了数据传输通道,就可以在该通道通过IO流进行数据的读取和写入。该通道称为Socket流,Socket流中既有读取流,也有写入流。
3.通过Socket对象获取这两个流。
4.通过流对象,可以对数据进行传输。
5.传输完毕,关闭资源。
/*客户端:
* socket:该类是客户端套接字
*
构造方法:public Socket(InetAddress address ,int port)throws IOException创建一个流套接字并将其连接到指定 IP 地址的指定端口号
public Socket(String host, int port)throws UnknownHostException, IOException创建一个流套接字并将其连接到指定主机上的指定端口号。
成员方法:
* public OutputStream getOutputStream()throws IOException返回此套接字的输出流。
*
*
如何创建客户端:
* 1. 建立客户端Socket服务,明确建立连接的IP和端口
* 2.如果连接成功,就可以通过IO流来实现传输
* 3.关闭客户端
*
* 异常:java.net.ConnectException: Connection refused: connect
* 连接被拒绝。(三次握手)
* */
public class ClientDemo {
public static void main(String[] args) throws IOException {
//Socket s=new Socket(InetAddress.getByName("192.168.0.102"),6666);
Socket s=new Socket("192.168.0.102",6666);
OutputStream os=s.getOutputStream();
os.write("hanxiaoHelloJava".getBytes());
s.close();
}
}
3.TCP接收端传输步骤:
1.建立服务器端的Socket服务,需要一个端口
2.服务器没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通讯
3.通过客户端的获取流对象的方法,读取数据或者写入数据
4.如果服务器完成,然后需要关闭客户端,然后关闭服务器。但是现实中一般情况向下是不会关闭服务器的,因为要一致提供服务。
/*
* 服务端:ServerSocket:
* 概述:该类实现了服务端套接字
* 构造方法:public ServerSocket(int port) throws IOException
* 成员方法:public Socket accept()throws IOException侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
*
* 如何创建服务端:
* 1.建立服务端Socket,这里要明确端口号
* 2.通过accept方法获取客户端对象
* 3.通过客户端对象的流操作,接收数据
* 4.如果我们数据传输完毕,就可以关闭服务器,但是一般不管服务器,保持一致*/
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(6666);
//通过accept方法
Socket s = ss.accept();
//接受输入流
InputStream is = s.getInputStream();
byte[]bytes=new byte[1024];
int len=is.read(bytes);
System.out.println(new String(bytes,0,len));
s.close();
//ss.close();
}
}
4.Server端给反馈
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(1111);
Socket s = ss.accept();
InputStream is = s.getInputStream();
byte[]bytes=new byte[1024];
int len =is.read(bytes);
System.out.println(new String(bytes,0,len));
OutputStream os = s.getOutputStream();
os.write("我已接收到你的数据".getBytes());
}
}
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket s=new Socket("192.168.0.102",1111);
OutputStream os = s.getOutputStream();
os.write("你好,未来的你".getBytes());
InputStream is = s.getInputStream();
byte[]bytes=new byte[1024];
int len=is.read(bytes);
System.out.println(new String(bytes,0,len));
}
}
5.客户端录入,服务器端在控制台和文本文件分别输出
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket s=new Socket("192.168.0.102",1111);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line=null;
while((line=br.readLine())!=null){
if("88".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
//br.close();
//bw.close();
s.close();
}
}
public class ReceviceDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(1111);
Socket s = ss.accept();
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
//定义文本文件
BufferedWriter bw=new BufferedWriter(new FileWriter("TCP.txt"));
String line =null;
while((line =br.readLine())!=null){
//System.out.println(line);//接收到服务端
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
}
}
6.出现小问题
按照我们思路,如果服务端一旦给了反馈,就会发生两边卡住;因为服务端不知道客服端发送完成,一直处于等待状态,而客户端已经发送完成也在等待服务器反馈,所以两端互相等待
7.如何处理
1.我给你一个指示,让你录到地方停止即可。
2.shutdownOutPut()java自带方法停止
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket s=new Socket("192.168.0.102",1111);
BufferedReader br=new BufferedReader(new FileReader("copy.txt"));
//BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line=null;
while((line=br.readLine())!=null){
/*if("88".equals(line)){
break;
}*/
bw.write(line);
bw.newLine();
bw.flush();
}
s.shutdownOutput();
/*bw.write("88");
bw.newLine();
bw.flush();*/
BufferedReader clientbr=new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(clientbr.readLine());//阻塞
s.close();
}
}
public class ReceviceDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(1111);
Socket s = ss.accept();//阻塞
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
//定义文本文件
BufferedWriter bw=new BufferedWriter(new FileWriter("tcp.txt"));
String line =null;
while((line =br.readLine())!=null){//阻塞
//System.out.println(line);//接收到服务端
/* if("88".equals(line)){
break;
}*/
bw.write(line);
bw.newLine();
bw.flush();
}
BufferedWriter serverBw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
serverBw.write("上传文件成功");
serverBw.newLine();//阻塞
serverBw.flush();
s.close();
//br.close();
//bw.close();
s.close();
}
}
8.上传文件
public class UPLoadServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket=new ServerSocket(6666);
System.out.println("等待客户端连接......");
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress().getHostAddress()+"已连接....");
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("b.jpg"));
byte[]bytes=new byte[1024];
int len=0;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
BufferedWriter serverBw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
serverBw.write("上传文件成功");
serverBw.newLine();//阻塞
serverBw.flush();
serverSocket.close();
serverSocket.close();
}
}
//文件上传
/*分析:
客户端端
文件---->内存
内存--->Socket通道
服务端
Socket通道---->内存
内存----->文件*/
public class UPLoadClient {
public static void main(String[] args) throws IOException {
Socket socket=new Socket("hx",6666);
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("E:\\hx.jpg"));
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[]bytes=new byte[1024];
int len=0;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
socket.shutdownOutput();
BufferedReader clientbr=new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(clientbr.readLine());//阻塞
socket.close();
socket.close();
}
}
s IOException {
Socket socket=new Socket(“hx”,6666);
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(“E:\hx.jpg”));
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[]bytes=new byte[1024];
int len=0;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
socket.shutdownOutput();
BufferedReader clientbr=new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(clientbr.readLine());//阻塞
socket.close();
socket.close();
}
}