• 【Java网络编程】二


    本文主要介绍了传输层的UDP协议和TCP协议,以及在Java中如何通过Socket套接字实现网络编程(内附UDP和TCP版本的回显服务器代码)

    一.网络通信

    网络编程,就是写一个应用程序,让这个程序可以使用网络通信,这里就需要调用传输层提供的api了。

    严格的来说,两台主机进行通信就是两台主机中的应用进程进行通信。

    通信的两端应该是两个主机中的应用进程。

    端到端的通信是应用进程之间的通信。

    传输层和网络层的区别

    网络层为主机之间的通信提供服务;

    运输层在网络层的基础上,为应用进程提供通信服务;

    二.传输层协议

    传输层协议,主要有两个:

    1.UDP 用户数据报协议

    2.TCP传输控制协议

    提供了两套不同的api,也叫做socket 套接字。

    UDP和TCP对比:

    UDP:无连接,不可靠传输,面向数据报,全双工

    TCP:有连接,可靠传输,面向字节流,全双工

    注意:

    有连接就相当于使用一块内存来保存对端的信息,双方都保存这个信息,此时连接就出现了。

    可靠传输,并不是说A发给B的消息百分百能到达,而是A尽可能地把消息传给B,并且在传输失败地时候,A可以感知到,或者传输成功地时候,也可以知道自己成功了

    TCp是可靠传输,但是传输效率降低了

    UDp是不可靠传输,但传输效率更高

    并且这也不意味着,TCP更安全,网络安全更多指的是数据是否容易被黑客截获

    面向字节流 VS 面向数据报

    TCP 和文件操作类似,都是流式的,而且传输的单位是字节,故称字节流

    UDP面向数据报,读写的基本单位是一个UDP数据报

    全双工 VS 半双工

    全双工:一个通道,可以双向通信(双向车道)

    半双工:一个通道,只能单向通信(单向车道)

    再比如:网线也是全双工的,通常来说,网线一般有八根铜缆,四四一组,一部分负责一个方向,另一部分则负责另一个方向。

    三.UDP数据报协议

    Java对于UDP的socket api,有两个核心的类:

    1.DatagramSocket

    是一个Socket对象 

    注意:操作系统,使用文件这样的概念来管理一些软硬件资源

    对于网卡(计算机和外界局域网连接的网络设备)  -->  操作系统也是使用 文件 的方式来管理网卡的

    表示网卡的这类文件,就是socket文件

    Java中的socket对象,就对应系统里的socket文件(最终还是要落到网卡)

    结论:要进行网络通信,就必须调用网卡;

    调用网卡,就必须先创建socket对象;

    创建socket对象:

    构造方法:

    1没有参数 DatagramSocket()

    在客户端这边使用(客户端使用哪个端口,系统自动分配

    2有参数 DatagramSocket(int port)

    在服务器这边使用(服务器使用哪个端口,手动指定

    说明:

    服务器:需要有一个固定的端口号,方便其他客户端找到

    比如,食堂的16号窗口,就相当于服务器的IP地址和端口号,此时有一个同学来食堂16号窗口吃饭,它坐的位置不需要是固定的,这就相当于是是客户端端口号。

    客户端:主机上面运行的程序很多,我们不知道手动指定的端口是不是被别的程序占用了,因此更合理的做法是让系统自动分配一个空闲的端口号。

    其他方法:

    1. receive(DatagramPacket p) 接收
    • send (DatagramPacket p)发送

    Close 关闭

    2.DatagramPacket

    表示一个UDP数据报

    代表了系统中设定的UDP数据报的二进制结构

    构造方法:

    说明:作为UDP数据报,必然要承载一些数据,通过手动指定的byte[]作为存储数据的空间。

    其他方法:

    3.回显服务器 

    回显服务器:客户端发什么,服务器就返回什么。

    >服务器代码:

    1. import java.io.IOException;
    2. import java.net.DatagramPacket;
    3. import java.net.DatagramSocket;
    4. import java.net.SocketException;
    5. /**
    6. * 实现一个回显服务器
    7. * 客户端发什么,服务器返回什么
    8. *
    9. */
    10. public class UdpEchoServer {
    11. private DatagramSocket socket=null;
    12. public UdpEchoServer(int port) throws SocketException {
    13. socket=new DatagramSocket(port);
    14. }
    15. /**
    16. * 启动服务器
    17. *
    18. * 反复的长期的执行
    19. * @param
    20. */
    21. public void start() throws IOException {
    22. System.out.println("服务器启动");
    23. while(true){
    24. //1读取请求,并解析
    25. /**
    26. * receive的参数是datagramPacket,是一个输出型参数,传入的receive
    27. 是一个空的对象,receive内部会把这会填充这个对象
    28. 当执行完就会得到一个转满内容的打他gramPacket
    29. */
    30. DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
    31. /**datagrampacket对象是用来保存数据的内存时间,需要手动指定,不像集合类,内部可以自己管理内存
    32. 第二个参数可以随便写,不能写太大。
    33. 如果客户端的请求还没来,receive就会阻塞等待,直到有客户端发起请求过来了
    34. */
    35. socket.receive(requestPacket);
    36. /**
    37. * 获得请求的内容
    38. * 这样的转字符串的前提是,后续客户端发起的数据就是一个文本的字符串
    39. *
    40. */
    41. String request=new String(requestPacket.getData(),0, requestPacket.getLength());
    42. //2根据请求,计算出相应(回显服务器,请求是啥,返回就是啥)
    43. /**
    44. * 由于是回显服务器,请求是啥,响应就是啥
    45. */
    46. String response=process(request);
    47. //3把响应写给客户端
    48. /**
    49. * 此时需要告诉网卡,要发的内容是啥,要发给谁
    50. * 构造一个datagramPacket对象,把响应发给客户端
    51. */
    52. DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,
    53. requestPacket.getSocketAddress());
    54. /**
    55. * 把数据包发给客户端,就需要直到客户端的ip和端口
    56. * datagrampacket这个对象里面包含着通信双方的ip和port
    57. */
    58. socket.send(responsePacket);
    59. //打印日志信息
    60. System.out.printf("%s:%d req:%s,resp:%s \n",requestPacket.getAddress().toString(),
    61. responsePacket.getPort(),request,response);
    62. }
    63. }
    64. //根据请求计算响应
    65. public String process(String request){
    66. return request;
    67. }
    68. public static void main(String[] args) throws IOException {
    69. UdpEchoServer server=new UdpEchoServer(9090);
    70. server.start();
    71. }
    72. }

    >客户端代码:

    1. import java.io.IOException;
    2. import java.net.*;
    3. import java.util.Scanner;
    4. /**
    5. * 实现一个udp的回显服务器
    6. * 客户端
    7. *
    8. */
    9. public class UdpEchoClient {
    10. private DatagramSocket socket=null;
    11. private String serverIp;
    12. private int serverPort;
    13. //服务器的ip和服务器的端口
    14. public UdpEchoClient(String ip,int port) throws SocketException {
    15. serverIp=ip;
    16. serverPort=port;
    17. //这个new操作,就不用再指定端口了,让系统自动分配一个空闲端口
    18. socket=new DatagramSocket();
    19. }
    20. /**
    21. * 让这个客户端反复的从控制台读取用户输入的内容,把这个内容构造成udp请求,发给服务器,再读取
    22. * 服务器返回的udp响应
    23. * 最终再显示在客户端的屏幕上
    24. */
    25. public void start() throws IOException {
    26. System.out.println("客户端启动");
    27. Scanner scanner=new Scanner(System.in);
    28. while(true){
    29. //1.从控制台读取用户输入的内容
    30. System.out.println("->");
    31. String request=scanner.next();
    32. //2.构造请求对象,并发送给服务器
    33. DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,
    34. InetAddress.getByName(serverIp),serverPort);
    35. socket.send(requestPacket);
    36. //3.读取服务器的响应,并解析出响应内容
    37. DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);
    38. socket.receive(responsePacket);
    39. String response=new String(responsePacket.getData(),0,responsePacket.getLength());
    40. //显示到屏幕上
    41. System.out.println(response);
    42. }
    43. }
    44. public static void main(String[] args) throws IOException {
    45. //云服务器ip地址
    46. // UdpEchoClient client=new UdpEchoClient("8.130.66.119",9090);
    47. UdpEchoClient client=new UdpEchoClient("127.0.0.1",9090);
    48. client.start();
    49. }
    50. }

    另外,我们也可以把服务器代码打一个jar包,放到云服务器上,然后访问云服务器的地址ip地址。

    IDEA手动打包方式:

    1.

    2.

    3.选择入口类,选择jar包存放的路径,jar包就生成了

    后面可以用Mobaxterm把这个jar包放到云服务器上去.....就不演示了

    四.TCP传输控制协议

    TCP提供的api也是主要的两个类

    1.ServerSocket

    服务器使用的socket

    2.Socket

    既会给服务器使用,也会给客户端使用


    TCP版本的回显服务器代码放在 【Java网络原理】三

  • 相关阅读:
    VMware虚拟机安装Linux系统的介绍
    131.【MySQL_基础篇】
    3d呈现transfrom-style
    Elasticsearch
    Ubuntu 20.04.5安装无线网卡RTL8821CE驱动
    在 Wed 中应用 MyBatis(同时使用MVC架构模式,以及ThreadLocal 事务控制)
    给出一组正整数arr,你从第0个数向最后一个数,每个数的值表示你从这个位置可以向右跳跃的最大长度,计算如何以最少的跳跃次数跳到最后一个数。
    TPM分析笔记(七)Start-up相关命令字
    ctf之:《kali-linux-2022-W48-virtualbox-amd64》工具测试netdiscover
    C++ Reference: Standard C++ Library reference: Containers: deque: deque: rbegin
  • 原文地址:https://blog.csdn.net/weixin_63210321/article/details/134012939