通过基于java实现的网络聊天程序分析java中网络API和Linux Socket API关系

1. 引言

  socket网络编程,可以指定不同的通信协议,在这里,我们使用TCP协议实现基于java的C/S模式下“hello/hi”网络聊天程序

2. 目标

  1). 通过该网络聊天程序,了解java Socket API接口的基本用法

  2). java Socket API简要介绍

  3). linux socket API 简单分析

  4). tcp协议的连接和终止

  5). 探究java socket API 和 linux socket api之间的关系

3. linux socket API简单分析

  

  1). 简要介绍一下 tcp协议

    tcp协议提供了可靠的面向连接的字节流运输层服务协议, 它将用户数据打包生成一个报文段发送出去,同时启动一个定时器;接收端则会对数据进行确认,重排失序的数据,并丢弃重复数据。

    tcp面向连接,意味着每次发送数据要先在两端间建立连接; 终止发送也要关闭连接

    a). 建立连接

      客户端: 请求发送方;  服务端: 数据接收方

      tcp通过三次握手来建立连接

      客户端先发送一个报文段,执行主动打开 -->  服务器发回一个SYN报文段作为应答 --> 客户端再发送一个报文段对服务器的应答进行确认

    b). 终止连接

      tcp需要四次握手来关闭连接,因为tcp连接时全双工,两个方向上的都要关闭,而每次的关闭都需要确认,由此需要四次握手

  2). API 分析

      a). 建立和终止

      客户端在调用connect()方法时候,会进行三次握手来建立连接,只有连接建立成功/失败的时候才会返回

      在此之前,服务端会一直阻塞等待客户端的请求

      当连接建立成功的时候,客户端和服务端进行数据传输

      传输结束后,客户端调用close()方法,

    b). bind

      会将本地协议地址赋予一个套接口

    c). listen

      当服务端调用socket(),会假定这是一个主动连接(即将调用connect发起连接的客户套接口),而listen()则将其转为被动连接,让内核接收指向该套接口的连接请求

      内核维护两个队列:未完成连接队列,已完成连接队列

    d). accept

      当客户端connect的时候,会在服务端的未完成连接队列中创建一个条目,当连接完成时候,将该条目移动到已完成连接队列中

      accept则从已完成连接队列中拿到一个已完成连接

4. 基于java的“hello/hi”网络聊天程序的简单实现

 1 import java.io.*;
 2 import java.net.ServerSocket;
 3 import java.net.Socket;
 4
 5 public class Server {
 6     public static void main(String[] args) throws Exception {
 7         System.out.println("服务端启动 , 等待连接 .... ");
 8         // 1. 创建 ServerSocket对象,绑定端口,开始等待连接
 9         ServerSocket server = new ServerSocket(6666);
10         // 2. 接收连接 accept 方法, 返回 socket 对象; 此方法在连接传入之前一直阻塞,返回新的套接字
11         Socket socket = server.accept();
12         // 3. 获取输入流
13         InputStream is = socket.getInputStream();
14         // 4. 一次性读取数据
15         byte[] b = new byte[1024];
16         int len = is.read(b);
17         // 解析数组
18         String msg = new String(b, 0, len);
19         System.out.println("From Client-> "+msg);
20
21         // 5. 获取输出流, 向客户端写入数据
22         OutputStream out = socket.getOutputStream();
23         out.write("Hi".getBytes());
24         // 关闭资源
25         out.close();
26         is.close();
27         server.close();
28     }
29 }
 1 import java.io.*;
 2 import java.net.Socket;
 3
 4 public class Client {
 5     public static void main(String[] args) throws Exception {
 6         System.out.println("客户端 发送数据");
 7         // 1. 创建 Socket , 确定连接到哪里
 8         Socket client = new Socket("localhost", 6666);
 9         // 2. 获取输出流
10         OutputStream os = client.getOutputStream();
11         // 3. 写出数据
12         os.write("Hello".getBytes());
13         // 4. 获取输入流,获取服务端返回的信息
14         InputStream in = client.getInputStream();
15
16         // 5.读取服务端返回的数据
17         byte[] b = new byte[100];
18         int len = in.read(b);
19         System.out.println("From Sever-> "+new String(b, 0, len));
20         // 5. 关闭资源
21         in.close();
22         os.close();
23         client.close();
24     }
25 }

5. java socket API 和 linux socket api 关系探究

  由上面的程序,我们可以观察到java中 server端相比linux下少了bind()和listen()两个方法, 客户端也没有connect()方法

  我们看一下Java和Linux Sever端API 对应关系,下面是网上的一张图,网络来源(https://blog.csdn.net/vipshop_fin_dev/article/details/102966081)

  

    当运行在linux系统上的时候,jvm会调用linux底层socket()函数,我们比较一下服务端的对应API

  a. ServerSocket server = new ServerSocket(6666);  会先创建一个socket,而其底层(对应的linux api)是实现了下面三个过程:

    1. 创建socket

      若要执行网络I/O,进程首先就要调用一个socket函数,并会指定一个期望的协议类型和套接口类型

      socket函数成功的时候会返回一个小的非负整数, 因在Linux中一切皆文件,所以这个整数表示一个文件描述符

      此时会创建socket对应的结构,并将其和一个已经打开的文件对应

    2. 将对应socket和本地协议地址对应(bind函数)

      对于TCP协议,bind函数可以和一个IP和一个端口绑定;此时该套接口处于TCP_CLOSE状态

      如果不绑定端口号,则内核会为该套接口绑定一个临时的端口

      如果不绑定IP地址,对于服务端而言,内核就会将客户端发送的SYN的目的IP地址作为服务器的源IP地址

    3. listen()监听

      由上面可以知道,listen会将主动转为被动连接,会将套接口由closed状态转换为linsten状态;并且维护了两个队列

      此时会和客户端进行三次握手来建立连接

      

  b. Socket socket = server.accept();

    linux中由TCP服务器调用,从已完成的连接队列的队头返回下一个已完成连接;成功则会返回由内核创建的新的描述符;

    在并发服务器中,accept()返回后,服务器会调用fork函数,创建一个子进程,由该子进程来和客户端进行通讯,此时套接口对应文件描述符的引用计数会增加

    同时父进程会关闭该已连接套接字,即会将引用计数减少。然后在原有的监听套接口上,继续监听有无其他连接,当由连接的时候,再次accept处理连接

  c. server.close();

    当待关闭的socket的描述符的引用计数为0的时候才会真正的关闭连接

参考来源:

  1. https://blog.csdn.net/vipshop_fin_dev/article/details/102966081

  2. 《UNIX网络编程》

原文地址:https://www.cnblogs.com/zhouz/p/11980538.html

时间: 2024-10-27 12:12:39

通过基于java实现的网络聊天程序分析java中网络API和Linux Socket API关系的相关文章

一个hello/hi的简单的网络聊天程序和python Socket API与Linux Socket API之间的关系

1.Socket概述 套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开.读写和关闭等操作.套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信.网络套接字是IP地址与端口的组合. 套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点.通信时,其中的一个网络应用程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过网络接口卡的传输介质将这段信息发送给另一台主机的Socket中,使这段信息能传送到

ubuntu系统下使用python3实现简单的网络聊天程序

这是我的第二篇博客,很遗憾第一篇博客没有得到应有的认可. 可能是因为原理介绍和实操部分不够多,只是单纯分析了某一条指令在打开网页过程中,输出的变化. 在我的第二篇博客中把相关原理介绍的更加详细了,同时丰富了程序代码部分的介绍. 本文对通信相关知识点(如socket套接字.TCP/IP.HTTP通信协议).hello/hi网络聊天程序代码.python socke接口与Linux socket api之间的关系三个方面做了相关介绍 一.网络通信相关知识 首先必须明确一点,我们进行网络通信之前,必须

基于Java实现hello/hi简单网络聊天程序

目录 Socket简要阐述 Socket的概念 Socket原理 hello/hi的简单网络聊天程序实现 服务器端 客户端 程序执行结果 跟踪分析调用栈 & Linux API对比 创建ServerSocket 调用栈图示 源码分析 Socket绑定 调用栈图示 源码分析 Socket监听 调用栈图示 源码分析 Socket Accept 调用栈图示 源码分析 Java Socekt API与Linux Socket API 参考链接 Socket简要阐述 Socket的概念 Socket的英文

实现一个的简单的网络聊天程序

本次实验采用Java语言,编写了一个简单的聊天室程序,可以实现多人之间的聊天.以下将对该程序进行详尽分析,并对比分析该编程语言提供的网络接口API与Linux Socket API之间的关系. 1. 网络通信相关要素 1) 协议 通信的协议还是比较复杂的, java.net 包中包含的类和接口,它们提供低层次的通信细节.我们可以直接使用这 些类和接口,来专注于网络程序开发,而不用考虑通信的细节. java.net 包中提供了两种常见的网络协议的支持: TCP:传输控制协议 (Transmissi

hello/hi的简单的网络聊天程序

一.TCP/IP协议族 要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何在它们之间传输的标准,从字面意思来看TCP/IP是TCP和IP协议的合称,但实际上TCP/IP协议是指因特网整个TCP/IP协议族.不同于ISO模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中. Internet

java实现hello/hi的简单的网络聊天程序与ServerSocket调用栈跟踪

java实现hello/hi的简单的网络聊天程序 网络聊天采用TCP协议通过java实现 import java.io.*; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception{ Socket socket = new Socket("192.168.31.68", 6666); BufferedReader reader = new

基于Python完成一个hello/hi的简单的网络聊天程序

一.Socket 套接字简介 套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开.读写和关闭等操作.套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信.网络套接字是IP地址与端口的组合. 传输层实现端到端的通信,因此,每一个传输层连接有两个端点.那么,传输层连接的端点是什么呢?不是主机,不是主机的IP地址,不是应用进程,也不是传输层的协议端口.传输层连接的端点叫做套接字(socket).根据RFC793的定义:端口号拼接到IP

Java实现一个简单的网络聊天程序

一.TCP通信概述 TCP协议是面向连接的通信协议,在传输数据之前,发送端和接收端必须建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输. 在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过三次握手. 三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠. ·第一次握手,客户端向服务器端发出连接请求,等待服务器确认. ·第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求.

基于C# Winform的简易聊天程序[第一篇-两端通信]

程序简介 本聊天程序支持局域网内部客户端与服务端之间的互相通信. 原理 启动服务端后,服务端通过持续监听客户端发来的请求,一旦监听到客户端传来的信息后,两端便可以互发信息了.服务端需要绑定一个IP,用于客户端在网络中寻找并建立连接.信息发送原理:将手动输入字符串信息转换成机器可以识别的字节数组,然后调用套接字的Send()方法将字节数组发送出去.信息接收原理:调用套接字的Receive()方法,获取对端传来的字节数组,然后将其转换成人可以读懂的字符串信息. 界面设计 - 服务端 IP文本框 na