网络编程基础

Java的学习之路 发表于 2022/03/24 10:38:45 2022/03/24
【摘要】 网络编程基础 一、网络的相关概念 1.网络通信 2.网络网络编程的目的:直接或间接地通过网络协议与其他计算机实现数据交换进行通讯要想实现网络编程,需要关注两个问题:1.如何准确定位网络上的一台或多台主机,定位主机上的特定应用2.找到主机以后怎么进行可靠高效的数据传输 3 .IP地址IP地址就是网络上定位的一台主机,端口号就是定位这台主机是哪一个应用在进行通信,端口号用来区分一台主机上面的不...

网络编程基础

一、网络的相关概念

1.网络通信

在这里插入图片描述

2.网络

在这里插入图片描述
网络编程的目的:直接或间接地通过网络协议与其他计算机实现数据交换进行通讯
要想实现网络编程,需要关注两个问题:
1.如何准确定位网络上的一台或多台主机,定位主机上的特定应用
2.找到主机以后怎么进行可靠高效的数据传输

3 .IP地址

在这里插入图片描述
IP地址就是网络上定位的一台主机,端口号就是定位这台主机是哪一个应用在进行通信,端口号用来区分一台主机上面的不同应用程序
在这里插入图片描述

4.ipv4地址分类

在这里插入图片描述
在这里插入图片描述

5.域名和端口号

比如说我们想要访问一个网站,由于IP地址难以记忆,我们一般在浏览器上写的是域名,域名经过DNS域名解析服务器,会把域名解析出来,看它的IP是多少,解析完以后,再拿这个IP地址去访问对应的服务器,就可以把这个资源访问到了
在这里插入图片描述
不同的进程对应不同的端口号
端口号与IP地址的组合得出一个网络套接字:Socket
在这里插入图片描述
一个服务要接收和发送数据的话,需要有一个端口。端口就类似于人的耳朵,我们要听懂别人的话,必须要有耳朵

在这里插入图片描述

6.网络通信协议

!

在这里插入图片描述
在这里插入图片描述

OSI模型过于理想化,没有被广泛推广
在这里插入图片描述

7. TCP和UDP

在这里插入图片描述
TCP类似于打电话
UDP类似于发短信
TCP三次握手
举一个生活中的小例子:打电话
打电话的时候,假设一个叫tom,一个叫kim,tom想要打电话和kim说事情,这个时候,电话必须打通,才可以传递信息,就类似于TCP连接。为了确保kim有在听,tom在传递信息之前先问一句,你在听吗?kim听到后就回说在听,然后tom就说我要开始说事情了,紧接着开始说事情
在这里插入图片描述
UDP协议无法保证传输的数据一定被接收到
UDP协议就是没有确认对方是否能够接收到消息,就直接传输信息
比如说:你发送信息给别人,但是这个电话号码可能停机了或者说注销了,你不能确保别人能接收消息,类似于UDP协议
在这里插入图片描述
假如说现在有一个人也想要打电话给kim,由于kim这个时候在和tom打电话,他们两个如果电话没有挂掉,这个人的电话是打不通的,就类似于TCP协议要释放已经建立的连接

tom发信息给kim,另外一个人同样也可以发信息给kim,就类似于UDP协议不需要释放资源

在这里插入图片描述

二、InetAddress 类

一个InetAddress类的对象就当于是一个IP地址

//File file=new File(“hello.txt”);
//比如说在这里file就对应内存中的hello.txt这个文件
//类似于这个
//inet1就对应一个具体的IP地址
InetAddress inet1=InetAddress.getByName(“192.168.10.14”);
//写上主机名就可以返回对应的对象

1.相关方法

getByName(String host) 、 getLocalHost()
两个常用方法:getHostName() 获取域名 / getHostAddress() 获取主机地址
在这里插入图片描述

2.实例操作

在这里插入图片描述

package com.zyh.java;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**InetAddress类的使用
 * @author zengyihong
 * @create 2022--02--27 8:46
 */
public class InetAddressMethod {
    public static void main(String[] args) throws UnknownHostException {
  //获取本机的InetAddress对象
        InetAddress localHost = InetAddress.getLocalHost();
        
        //计算机名称和识别到的ip地址
        System.out.println(localHost);

        //我们也可以根据主机名来获取InetAddress对象
        InetAddress byName = InetAddress.getByName("这里写上你的主机名");
        System.out.println("host="+byName);

        //根据域名来返回InetAddress对象
        InetAddress byName1 = InetAddress.getByName("www.baidu.com");
        System.out.println("百度:"+byName1);

        //根据InetAddress对象获取对呀的主机地址
        String hostAddress = byName1.getHostAddress();
        System.out.println(hostAddress);//ip地址

        //通过InetAddress对象,获取对应的主机名或者域名
        String hostName = byName1.getHostName();
        System.out.println(hostName);

    }
}

三、Socket

Socket就类似于通信的通道,发送数据是通过socket
在这里插入图片描述
在这里插入图片描述

两台主机要通信首先要建立连接,就相当于是建立一个数据通道

客户端发起连接,服务器端接收连接就会形成这样一个数据通道

Socket有两个编程方式:TCP编程和UDP编程

1.TCP网络通信编程

1.1基本介绍

在这里插入图片描述
Socket最后记得关闭,不然连接越来越多,最后就导致无法连接

1.2案例1:客户端发送信息给服务端

在这里插入图片描述
思路:
在这里插入图片描述
ServerSocket可以有多个Socket,也就是说服务器端可以和多个客户端连接,否则就不能处理多并发问题
在这里插入图片描述
服务器端:

package com.zyh.java;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**服务器端
 * @author zengyihong
 * @create 2022--02--27 9:25
 */
public class SocketTCP01Server {
    public static void main(String[] args) throws IOException {
        //在本机的9999端口监听,等待连接
        //要求:本机没有其他服务监听这个端口
        //ServerSocket可以有多个Socket 通过accept可以返回多个Socket
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器端在9999端口等待连接...");
        //如果没有客户端连接此端口,程序就会阻塞,等待连接
        //如果有客户端连接,则返回Socket对象
        Socket socket = serverSocket.accept();
        //没有连接的话,下面的代码都不会运行

        System.out.println("服务器端 socket="+socket.getClass());

        System.out.println("服务器端开始接收信息");
        //连接以后要读取客户端发送的信息
        //通过IO读取
        InputStream inputStream = socket.getInputStream();
        byte[] bytes=new byte[10];
        int len;
        while ((len=inputStream.read(bytes))!=-1){
            String s = new String(bytes, 0, len);
            System.out.print (s);
        }
        //关闭流和socket
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

package com.zyh.java;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端
 *
 * @author zengyihong
 * @create 2022--02--27 9:31
 */
public class SocketTCP01Client {
    public static void main(String[] args) throws IOException {
    //连接服务器端 (ip,端口)
        //连接某一台主机的9999端口,如果连接成功,返回socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回="+socket.getClass());

        //连接上后,生成Socket,发送数据给服务端,通过socket,getOutputStream()
        //得到和socket对象关联的输出流对象
        System.out.println("客户端要开始发消息给服务端了");
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,server".getBytes());

        //关闭流对象和socket
        outputStream.close();
        socket.close();
        System.out.println("客户端退出");
    }
}

运行效果:

在服务器端:

服务器端在9999端口等待连接...
服务器端 socket=class java.net.Socket
hello,server

在客户端:

客户端 socket返回=class java.net.Socket
客户端退出

1.3案例2:客户端发信息给服务器端,并接收服务器端发回来的消息

在这里插入图片描述
在这里插入图片描述

注意:服务器端发消息给客户端的时候,客户端并不知道服务器端什么时候发送信息结束,也就是发送信息的时候,要有一个结束标记,不然就会一直等待,同样的,另外一个发送信息的时候,发送结束也应该要有一个结束标记,不然就不知道对方还要不要继续发送信息

服务器端:

package com.zyh.java;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**服务器端
 * @author zengyihong
 * @create 2022--02--27 9:25
 */
public class SocketTCP02Server {
    public static void main(String[] args) throws IOException {
        //在本机的9999端口监听,等待连接
        //要求:本机没有其他服务监听这个端口
        //ServerSocket可以有多个Socket 通过accept可以返回多个Socket
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器端在9999端口等待连接...");
        //如果没有客户端连接此端口,程序就会阻塞,等待连接
        //如果有客户端连接,则返回Socket对象
        Socket socket = serverSocket.accept();
        //没有连接的话,下面的代码都不会运行

        System.out.println("服务器端 socket="+socket.getClass());

        System.out.println("服务器端开始接收信息");
        //连接以后要读取客户端发送的信息
        //通过IO读取
        InputStream inputStream = socket.getInputStream();
        byte[] bytes=new byte[10];
        int len;
        while ((len=inputStream.read(bytes))!=-1){
            String s = new String(bytes, 0, len);
            System.out.print (s);
        }
        //获取 socket 相关联的输出流
	OutputStream outputStream = socket.getOutputStream();
	outputStream.write("hello, client".getBytes());
//      设置结束标记
	socket.shutdownOutput();
        //关闭流和socket
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

package com.zyh.java;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端
 *
 * @author zengyihong
 * @create 2022--02--27 9:31
 */
public class SocketTCP02Client {
    public static void main(String[] args) throws IOException {
    //连接服务器端 (ip,端口)
        //连接某一台主机的9999端口,如果连接成功,返回socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回="+socket.getClass());

        //连接上后,生成Socket,发送数据给服务端,通过socket,getOutputStream()
        //得到和socket对象关联的输出流对象
        System.out.println("客户端要开始发消息给服务端了");
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,server".getBytes());
        //      设置结束标记
socket.shutdownOutput();

//  获取和 socket 关联的输入流.  读取数据(字节) ,并显示
	InputStream inputStream = socket.getInputStream();
	byte[] buf = new byte[1024];
	int readLen = 0;
	while ((readLen = inputStream.read(buf)) != - 1) {
			System.out.println(new String(buf, 0, readLen));
	}

        //关闭流对象和socket
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端退出");
    }
}

运行效果:

在服务器端:
```xml
服务器端在9999端口等待连接...
服务器端 socket=class java.net.Socket
hello,server

在客户端:

客户端 socket返回=class java.net.Socket
hello,client
客户端退出

1.4案例3:使用字符流

在这里插入图片描述
在这里插入图片描述

客户端

package com.hspedu.socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

 
@SuppressWarnings({"all"})
public class SocketTCP03Server {
public static void main(String[] args) throws IOException {
//思路
//1.  在本机 的 9999 端口监听,  等待连接
//      细节:  要求在本机没有其它服务在监听 9999

//      细节: 这个 ServerSocket  可以通过 accept()  返回多个 Socket[多个客户端连接服务器的并发] ServerSocket serverSocket = new ServerSocket(9999);
	System.out.println("服务端,在 9999 端口监听,等待连接..");
//2.  当没有客户端连接 9999 端口时,程序会 阻塞,  等待连接
//      如果有客户端连接,则会返回 Socket 对象,程序继续
	Socket socket = serverSocket.accept();

	System.out.println("服务端 socket =" + socket.getClass());
//
//3.  通过 socket.getInputStream()  读取客户端写入到数据通道的数据,  显示
	InputStream inputStream = socket.getInputStream();
//4. IO 读取,  使用字符流,  使用 InputStreamReader  将 inputStream  转成字符流     
	BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
	String s = bufferedReader.readLine();
	System.out.println(s);//输出

//5.  获取 socket 相关联的输出流
	OutputStream outputStream = socket.getOutputStream();
//        使用字符输出流的方式回复信息
	BufferedWriter bufferedWriter = new BufferedWriter(new 	OutputStreamWriter(outputStream)); 
	bufferedWriter.write("hello client  字符流");
	bufferedWriter.newLine();//  插入一个换行符,表示回复内容的结束
	bufferedWriter.flush();//注意需要手动的 flush

	//6.关闭流和 socket
	bufferedWriter.close();
	bufferedReader.close();
	socket.close();
	serverSocket.close();//关闭	

}
}	

服务端:

package com.hspedu.socket;	
import java.io.*;
import java.net.InetAddress; import java.net.Socket;	
 

/**
*  
*  客户端,发送 "hello, server"  给服务端, 使用字符流 */
@SuppressWarnings({"all"})
public class SocketTCP03Client {
public static void main(String[] args) throws IOException {
//思路
//1.  连接服务端 (ip ,  端口)
//解读:  连接本机的 9999 端口,  如果连接成功,返回 Socket 对象
	Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
	System.out.println("客户端 socket 返回=" + socket.getClass());
//2.  连接上后,生成 Socket,  通过 socket.getOutputStream()
//      得到 和 socket 对象关联的输出流对象
	OutputStream outputStream = socket.getOutputStream();
//3.  通过输出流,写入数据到 数据通道,  使用字符流
	BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); 
	bufferedWriter.write("hello, server  字符流");
	bufferedWriter.newLine();
	//插入一个换行符,表示写入的内容结束,  注意,要求对方使用 readLine()
	//!!!! bufferedWriter.flush();
	//  如果使用的字符流,需要手动刷新,否则数据不会写入数据通道



//4.  获取和 socket 关联的输入流.  读取数据(字符) ,并显示
	InputStream inputStream = socket.getInputStream();
	BufferedReader bufferedReader = new BufferedReader(new 	InputStreamReader(inputStream)); String s = bufferedReader.readLine();
	System.out.println(s);

//5.  关闭流对象和 socket,  必须关闭
	bufferedReader.close();//关闭外层流
	bufferedWriter.close();
	socket.close();
	System.out.println("客户端退出.....");
}
}

运行结果:
在这里插入图片描述
在这里插入图片描述

1.5案例4:发送图片

在这里插入图片描述
在这里插入图片描述

1.6netstat指令

在这里插入图片描述
在这里插入图片描述

netstat - anb表示我们在查看程序的时候,知道是哪一个程序在占用这个端口

1.7 TCP 网络通讯不为人知的秘密

在这里插入图片描述
在这里插入图片描述

当客户端和服务器连接成功以后,客户端这里也有一个端口,它的端口是不确定的,是由TCP/IP分配的。客户端这里对应的端口和服务器端通讯

当传输结束以后,客户端的端口就被释放了

2.UDP网络编程(了解)

用得相对比较少,但是效率比较高

1. 基本介绍

在这里插入图片描述
在这里插入图片描述

2.基本流程

在这里插入图片描述
在这里插入图片描述

3.案例

在这里插入图片描述
在这里插入图片描述

package com.zyh.java.udptest;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**UDP接收端
 * @author zengyihong
 * @create 2022--02--27 12:38
 */
public class SocketUDP01Reciver {
    public static void main(String[] args) throws IOException {
        //创建一个DatagramSocket对象,准备在9999端口接收数据
        DatagramSocket datagramSocket=new DatagramSocket(9999);
        //创建 DatagramPacket对象,准备接收数据
        //UDP数据包每一个大小被限制在64K内,不适合传输大量数据
        byte[] bytes=new byte[1024];
        DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length);

        //调用接收方法,把通过网络传输的DatagramPacket对象
        //填充到packet对象
        //会在9999端口等待,如果有数据包发送到此端口,就会接收到数据
        //如果没有数据包发送到9999端口,就会阻塞,一直等,直到有数据传输
        System.out.println("接收端A等待接收数据...");
        datagramSocket.receive(datagramPacket);

        //把datagramPacket进行拆包,取出数据,并显示
        //因为数据的传输被包装起来了
        //返回实际接收的长度
        int length = datagramPacket.getLength();
        //接收到的数据
        byte[] data = datagramPacket.getData();
        String s = new String(data, 0, length);
        System.out.println(s);
        //关闭资源
        datagramSocket.close();
        System.out.println("A端退出");
    }
}

package com.zyh.java.udptest;

import java.io.IOException;
import java.net.*;

/**UDP发送端
 * 发送端B也可以接收数据
 * 发送端将来也可以是接收端
 * @author zengyihong
 * @create 2022--02--27 12:39
 */
public class SocketUDP01Send {
    public static void main(String[] args) throws IOException {
        //创建DatagramSocket对象,准备发送和接收数据
        //准备在9998端口接收数据
        DatagramSocket socket=new DatagramSocket(9998);

        //把要发送的数据封装到DatagramPacket对象 内容字节数组,长度,主机(IP),端口
        byte[] buff= "hello,明天吃火锅".getBytes();
        //ipconfig可以查看网络配置
        DatagramPacket packet=new DatagramPacket(buff,buff.length,InetAddress.getLocalHost(),9999);

        //发送数据
        socket.send(packet);
        //关闭资源
        socket.close();
        System.out.println("B端退出");



    }
}

运行结果

接收端A等待接收数据...
hello,明天吃火锅
A端退出
B端退出```
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。