文章目录
- 1.网络初识
- 2.网络编程
- 2.1TCP/UDP区别介绍
- 2.2UDP的socket api使用
- 2.3UDP协议里面的服务器客户端程序
1.网络初识
网络和计算机类似:都是属于军用====》民用;
网络诞生于美苏争霸时期,当时就感觉核战争一触即发,形式非常严峻;
下面的这个就是网络的发展的简单的历程以及对于这个基本的网络知识的一个说明;
2.网络编程
网络编程就是通过网络,让主机之间可以建立通信的过程;
进行网络编程的时候,我们的这个操作系统会提供成套的这个aip接口供我们进行使用,我们通过对于这些api 的调用才可以完成这些的网络编程的过程;
api就可以认为是这个应用层和我们的这个传输层之间进行交互的一个路径,这类api的全程就是socket api,通过这套api接口,我们可以实现不同主机之间的这个不同系统之间的网络通信的过程;
传输层提供网络协议主要是两个,就是TCP/UDP协议,这两个协议之间的这个差别很大,我们使用这两套api进行网络编程的时候也是会存在较大的区别的;
2.1TCP/UDP区别介绍
1,有链接和无连接:就是TCP协议进行传输的时候,需要首先保存对方的信息,就是我们的这个发送方知道我们的这个信息会发给谁,我们的接收方知道这个信息是谁发过来的;
但是我们的这个UDP就不会这样确认保存对方的信息了,不需要征求对方的同意,而是会直接进行这个数据的发送,UDP在进行发送的时候也不会保存这个对方的信息;(但是我们写这个程序的程序员需要知道这个信息会发送给谁,我们调用这个socket api接口的时候,就会把这个发送位置信息传递过去);
2.可靠传输和不可靠传输:就是类似于这个医生看病,我们的这个医生对于一个病人的这个病情进行治疗的时候不会保证这个病人一定可以治疗好,或者是其他的,但是这个医生自己是有数的;
同上面的这个案例相似,我们的上面的这个TCP/UDP进行信息的传输的时候,TCP发送数据的时候,能不能发送成功他自己心里是有数的,虽然不是100%确定,但是自己并不是完全没有把握;
因此我们的这个TCP是内置这个可靠传输的协议的,但是我们的这个UDP是没有内置可靠传的,但是这个可靠传输的结果就是我们的这个传输的过程很繁琐,而且这个传输的效率很低;
3.字节流和数据报:字节流可以进行灵活的读写,这个就是TCP传输所面向的,但是我们的这个UDP是面向这个数据包传输的,一个UDP数据报是由很严格的格式的;
网络上面的数据通信的基本单位的几个不同的说法,虽然不同,但是我们一般会混用:
数据报:datagram
数据包:packet
数据帧:frame
数据段:segment
4.全双工的:一个信道可以进行双向的通信,如果是只能进行单向的通信,这个时候就是半双工的;
2.2UDP的socket api使用
datagramsocket:socket实际上也是我们的操作系统里面的概念,我们的这个socket实际上就是硬件里面的“网卡”的一个抽象;
我们往这个socket文件里面写数据实际是通过网卡发送数据,通过socket文件读数据就是通过网卡接收数据;
java里面有这个datagramsocket类表示系统内部的socket文件,本质上这个socket就是一个文件,对于这个socket的操作,实际上就是我们的这个网卡进行发送和接收数据;
这个类里面由receive,send,close等方法,我们的这个方法的参数就是我们的datagrampacket这个类,这个datagrampacket表示的就是我们的UDP的数据包;
datagrampacket:上面说了这个就是数据报,这个是进行传输的基本单位:
我们下面就是实现一个简单的UDP的客户端/服务器通信的程序,这个程序没有任何的业务逻辑,只是单纯的调用这个socket api,让我们的客户端发送请求,请求就是从这个控制台进行字符串的输入,服务器接收到这个字符串之后,就会把这个字符串原封不动的返回给我们的客户端,客户端会显示出来;
因为上面的这个服务器用户发送什么,我们的这个服务器就是会返回什么到客户端,因此这样的服务器被称之为回显服务器;
2.3UDP协议里面的服务器客户端程序
下面的这个是UDP的服务器端的程序:
import javax.xml.crypto.Data;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
@SuppressWarnings({"all"})
//下面的这个就是我们的服务器程序代码编写
public class UdpEchoServer {
//首先创建一个dtatsocket对象,这个是我们操作网卡的基础
private DatagramSocket socket = null;
public UdpEchoServer(int port) throws SocketException {
//下面的这个就是对于端口进行手动的指定
socket = new DatagramSocket(port);
//下面的这个就是自动分配端口,客户端自动分配端口,我们的服务器的端口需要制定
//socket = new DatagramSocket();
}
public void start() throws IOException {
System.out.println("服务器启动!!!");
//一个服务器程序里面经常会看到这个while(true)这样的代码
//服务器程序经常需要长时间运行,我们不知道客户端什么时候有请求
while(true){
/**
* 1.读取请求并且进行解析
*requestPacket需要对于接受的数据进行保存,但是这个datagrampacket无法自己分配内存,需要我们分配
*我们的这个服务器一旦启动,我们这个receive就会被执行到,如果这个时候我们的客户端的请求没有来
* 我们这个时候的receive就会进入阻塞的状态,直到我们接受到请求
*/
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
socket.receive(requestPacket);
/**
* 2.我们接受到这个数据是二进制数据,想要显示出来,需要进行转换
* 0,requestPacket.getLength这个空间里面的字节被取出来转换为这个字符串
* 这个getlength得到的结果不是上面指定的这个4096,而是这个里面真是的存储数据的真实空间长度
* 主要是取决于我们的这个发送方发送数据的多少
*/
String request = new String(requestPacket.getData(),0,requestPacket.getLength());
/**
* 3.下面的这个就是根据请求计算响应,因为我们的这个回显服务器就是直接把这个请求作为响应,所以基本上没咋处理
*/
String response=process(request);
/**
* 下面的这个就是把我们的响应写回到客户端,创建响应的对象
*/
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());
socket.send(responsePacket);
/**
* 4.进行日志的打印,把这个响应的相应信息打印出来
*/
System.out.printf("[%s:%d] rep=%s,resp=%s\n",requestPacket.getAddress().toString(),responsePacket.getPort(),request,response);
}
}
public String process(String response){
return response;
}
public static void main(String[] args) throws IOException {
UdpEchoServer server = new UdpEchoServer(9090);
server.start();
}
}
下面的这个就是UDP的客户端程序:
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
@SuppressWarnings({"all"})
public class UdpEchoClient {
private DatagramSocket socket = null;
private String serverIp="";
private int serverPort=0;
public UdpEchoClient(String ip,int port) throws SocketException {
//创建对象,但是不要手动指定端口
socket=new DatagramSocket();
/**
* 因为我们的这个UDP协议不会保存对方的信息,,因此在我们的这个里面需要把ip信息记录下来
*/
serverIp=ip;
serverPort=port;
}
public void start() throws IOException {
System.out.println("客户端启动!!!");
Scanner scanner = new Scanner(System.in);
while(true){
System.out.println("->");
String request=scanner.next();
//把请求内容构建对象,发送给服务器
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),serverPort);
socket.send(requestPacket);
//尝试读取服务器返回的响应
DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
socket.receive(responsePacket);
//把响应转换为字符串,打印输出
String response=new String(responsePacket.getData(),0,responsePacket.getLength());
System.out.println(response);
}
}
public static void main(String[] args) throws IOException {
UdpEchoClient client = new UdpEchoClient("192.168.137.0",9090);
client.start();
}
我们的这个执行的逻辑就是我们的这个服务器先启动,然后我们的客户端输入,服务器接受之后进行解析,返回响应(其实就是我们的输入的内容,因为这个是回显服务器),客户端接收响应,并且打印这个响应的内容;
我们的这个程序其他人还是访问不到的,除非我们在一个局域网上面,我们后面可以部署到这个云服务器上面,这样其他的人也是可以登陆的~~