我的编程空间,编程开发者的网络收藏夹
学习永远不晚

网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)

 

 

目录

Java网络编程中的常用类

TCP通信的实现和项目案例

TCP通信入门案例 

TCP单向通信

TCP双向通信

创建点对点的聊天应用

一对多应用

一对多聊天服务器


Java网络编程中的常用类

Java为了跨平台,在网络应用通信时是不允许直接调用操作系统接 口的,而是由java.net包来提供网络功能。下面我们来介绍几个 java.net包中的常用的类。

InetAddress的使用 

作用:封装计算机的IP地址和DNS(没有端口信息)

注:DNS是Domain Name System,域名系统。

特点:

这个类没有构造方法。如果要得到对象,只能通过静态方法:

getLocalHost()、getByName()、 getAllByName()、 getAddress()、getHostName()

 获取本机信息

获取本机信息需要使用getLocalHost方法创建InetAddress对象。 getLocalHost()方法返回一个InetAddress对象,这个对象包含了本 机的IP地址,计算机名等信息。

public class InetTest {    public static void main(String[] args)throws Exception {        //实例化InetAddress对象        InetAddress inetAddress = InetAddress.getLocalHost();        //返回当前计算机的IP地址      System.out.println(inetAddress.getHostAddress());        //返回当前计算机名      System.out.println(inetAddress.getHostName());   }}

根据域名获取计算机的信息

根据域名获取计算机信息时需要使用getByName(“域名”)方法创建 InetAddress对象。

public class InetTest2 {    public static void main(String[] args)throws Exception {        InetAddress inetAddress = InetAddress.getByName("www.baidu.com");      System.out.println(inetAddress.getHostAddress());      System.out.println(inetAddress.getHostName());   }}

根据IP获取计算机的信息

根据IP地址获取计算机信息时需要使用getByName(“IP”)方法创建 InetAddress对象。

public class InetTest3 {    public static void main(String[] args)throws  Exception {        InetAddress inetAddress = InetAddress.getByName("14.215.177.38");      System.out.println(inetAddress.getHostAddress());      System.out.println(inetAddress.getHostName());   }}

 InetSocketAddress的使用

作用:包含IP和端口信息,常用于Socket通信。此类实现 IP 套接字 地址(IP 地址 + 端口号),不依赖任何协议。 InetSocketAddress相比较InetAddress多了一个端口号,端口的作 用:一台拥有IP地址的主机可以提供许多服务,比如Web服务、 FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实 现。 那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址, 因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地 址+端口号”来区分不同的服务的。

public class InetSocketTest {    public static void main(String[] args) {        InetSocketAddress inetSocketAddress = new InetSocketAddress("www.baidu.com",80);      System.out.println(inetSocketAddress.getAddress().getHostAddress());      System.out.println(inetSocketAddress.getHostName());   }}

URL的使用

IP地址标识了Internet上唯一的计算机,而URL则标识了这些计算机 上的资源。 URL 代表一个统一资源定位符,它是指向互联网“资源” 的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对 象的引用,例如对数据库或搜索引擎的查询。 为了方便程序员编程,JDK中提供了URL类,该类的全名是 java.net.URL,有了这样一个类,就可以使用它的各种方法来对 URL对象进行分割、合并等处理。

public class UrlTest {    public static void main(String[] args)throws Exception {        URL url = new URL("https://www.itbaizhan.com/search.html?kw=java");        System.out.println("获取与此URL相关联协议的默认端口:"+url.getDefaultPort());        System.out.println("访问资源:"+url.getFile());        System.out.println("主机名"+url.getHost());        System.out.println("访问资源路径:"+url.getPath());        System.out.println("协议:"+url.getProtocol());        System.out.println("参数部分:"+url.getQuery());   }}

 通过URL实现最简单的网络爬虫

public class UrlTest2{    public static void main(String[] args)throws Exception {            URL url = new URL("https://www.itbaizhan.com/");            try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {             StringBuilder sb = new StringBuilder();                String temp;                     while ((temp = br.readLine()) != null) {                    sb.append(temp);               }                System.out.println(sb);           } catch (Exception e) {                e.printStackTrace();           }   }}

TCP通信的实现和项目案例

TCP通信实现原理

前边我们提到TCP协议是面向的连接的,在通信时客户端与服务器 端必须建立连接。在网络通讯中,第一次主动发起通讯的程序被称 作客户端(Client)程序,简称客户端,而在第一次通讯中等待连接的 程序被称作服务器端(Server)程序,简称服务器。一旦通讯建立,则 客户端和服务器端完全一样,没有本质的区别。

 “请求-响应”模式:

Socket类:发送TCP消息。

ServerSocket类:创建服务器。

 套接字Socket是一种进程间的数据交换机制。这些进程既可以在同 一机器上,也可以在通过网络连接的不同机器上。换句话说,套接 字起到通信端点的作用。单个套接字是一个端点,而一对套接字则 构成一个双向通信信道,使非关联进程可以在本地或通过网络进行 数据交换。一旦建立套接字连接,数据即可在相同或不同的系统中 双向或单向发送,直到其中一个端点关闭连接。套接字与主机地址 和端口地址相关联。主机地址就是客户端或服务器程序所在的主机 的IP地址。端口地址是指客户端或服务器程序使用的主机的通信端 口。 在客户端和服务器中,分别创建独立的Socket,并通过Socket的属 性,将两个Socket进行连接,这样,客户端和服务器通过套接字所 建立的连接使用输入输出流进行通信。 TCP/IP套接字是最可靠的双向流协议,使用TCP/IP可以发送任意数 量的数据。 实际上,套接字只是计算机上已编号的端口。如果发送方和接收方 计算机确定好端口,他们就可以通信了。 客户端与服务器端的通信关系图:

 

 TCP/IP通信连接的简单过程:

位于A计算机上的TCP/IP软件向B计算机发送包含端口号的消息,B 计算机的TCP/IP软件接收该消息,并进行检查,查看是否有它知道 的程序正在该端口上接收消息。如果有,他就将该消息交给这个程 序。 要使程序有效地运行,就必须有一个客户端和一个服务器。

 通过Socket的编程顺序:

1 创建服务器ServerSocket,在创建时,定义ServerSocket的监听端口(在这个端口接收客户端发来 的消息)

2 ServerSocket调用accept()方法,使之处于阻塞状态。

3 创建客户端Socket,并设置服务器的IP及端口。

4 客户端发出连接请求,建立连接。

5 分别取得服务器和客户端Socket的InputStream和OutputStream。

6 利用Socket和ServerSocket进行数据传输。

7 关闭流及Socket。

TCP通信入门案例 

创建服务端

public class BasicSocketServer {    public static void main(String[] args) {        System.out.println("服务器启动等待监听。。。。");        //创建ServerSocket        try(ServerSocket ss =new ServerSocket(8888);            //监听8888端口,此时线程会处于阻塞状态。            Socket socket = ss.accept();            //连接成功后会得到与客户端对应的 Socket对象,并解除线程阻塞。           //通过客户端对应的Socket对象中的输入流对象,获取客户端发送过来的消息。            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))       ){                   System.out.println(br.readLine());       }catch(Exception e){            e.printStackTrace();            System.out.println("服务器启动失败。。。。");       }   }}

创建客户端

public class BasicSocketClient {    public static void main(String[] args) {        //创建Socket对象        try(Socket socket =new Socket("127.0.01",8888);            //创建向服务端发送消息的输出流对象。            PrintWriter pw = new PrintWriter(socket.getOutputStream())){            pw.println("服务端,您好!");            pw.flush();       }catch(Exception e){            e.printStackTrace();       }   }}

TCP单向通信

单向通信是指通信双方中,一方固定为发送端,一方则固定为接收 端。

 创建服务端

public class OneWaySocketServer {    public static void main(String[] args) {        System.out.println("服务端启动,开始监听。。。。。");        try(ServerSocket serverSocket = new ServerSocket(8888);            //监听8888端口,获与取客户端对应的 Socket对象            Socket socket = serverSocket.accept();            //通过与客户端对应的Socket对象获取输入流对象            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));            //通过与客户端对应的Socket对象获取输出流对象            PrintWriter pw = new PrintWriter(socket.getOutputStream())){            System.out.println("连接成功!");            while(true){                //读取客户端发送的消息                String str = br.readLine();                System.out.println("客户端说:"+str);                if("exit".equals(str)){                    break;               }                pw.println(str);                pw.flush();           }       }catch(Exception e){            e.printStackTrace();            System.out.println("服务端启动失败。。。。。");       }   }}

创建客户端

public class OneWaySocketClient {    public static void main(String[] args) {        //获取与服务端对应的Socket对象        try(Socket socket = new Socket("127.0.0.1",8888);        //创建键盘输入对象            Scanner scanner = new Scanner(System.in);            //通过与服务端对应的Socket对象获取输出流对象            PrintWriter pw = new PrintWriter(socket.getOutputStream());            //通过与服务端对应的Socket对象获取输入流对象            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())))        {            while(true){                //通过键盘输入获取需要向服务端发送的消息                String str = scanner.nextLine();    //将消息发送到服务端                pw.println(str);                pw.flush();                if("exit".equals(str)){                    break;               }                //读取服务端返回的消息                String serverInput = br.readLine();               System.out.println("服务端返回的:"+serverInput);           }       }catch(Exception e){            e.printStackTrace();       }   }}

TCP双向通信

双向通信是指通信双方中,任何一方都可为发送端,任何一方都可 为接收端。

创建服务端

public class TwoWaySocketServer {    public static void main(String[] args) {        System.out.println("服务端启动!监听端口8888。。。。");        try(ServerSocket serverSocket  = new ServerSocket(8888);            Socket socket = serverSocket.accept();            //创建键盘输入对象            Scanner scanner = new Scanner(System.in);            //通过与客户端对应的Socket对象获取输入流对象            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));            //通过与客户单对应的Socket对象获取输出流对象            PrintWriter pw  = new PrintWriter(socket.getOutputStream());){            while(true){                //读取客户端发送的消息                String str = br.readLine();                System.out.println("客户端说:"+str);                String keyInput = scanner.nextLine();                //发送到客户端                pw.println(keyInput);                pw.flush();           }       }catch(Exception e){            e.printStackTrace();       }   }}

创建客户端

public class TwoWaySocketClient {    public static void main(String[] args) {        try(Socket socket = new Socket("127.0.0.1", 8888);            //创建键盘输入对象            Scanner  scanner = new Scanner(System.in);            //通过与服务端对应的Socket对象获取输入流对象            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));            //通过与服务端对应的Socket对象获取输出流对象            PrintWriter pw = new PrintWriter(socket.getOutputStream());){            while (true) {                String keyInput = scanner.nextLine();                pw.println(keyInput);                pw.flush();                String input = br.readLine();                System.out.println("服务端说:" + input);           }       } catch (Exception e) {            e.printStackTrace();       }   }}

创建点对点的聊天应用

创建服务端

class Send extends Thread{    private Socket socket;    public Send(Socket socket){        this.socket = socket;   }    @Override    public void run() {        this.sendMsg();   }        private void sendMsg(){        //创建Scanner对象        try(Scanner scanner = new Scanner(System.in);            //创建向对方输出消息的流对象            PrintWriter pw = new PrintWriter(this.socket.getOutputStream());)          {            while(true){                String msg = scanner.nextLine();                pw.println(msg);                pw.flush();           }       }catch(Exception e){            e.printStackTrace();       }   }}class Receive extends Thread{    private Socket socket;    public Receive(Socket socket){        this.socket = socket;   }    @Override    public void run() {        this.receiveMsg();   }        private void receiveMsg(){        //创建用于接收对方发送消息的流对象        try(BufferedReader  br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));){            while(true){                    String msg = br.readLine();                    System.out.println("他说:"+msg);           }       }catch(Exception e){            e.printStackTrace();       }   }}public class ChatSocketServer {    public static void main(String[] args) {        try(ServerSocket serverSocket = new ServerSocket(8888);){            System.out.println("服务端启动,等待连接。。。。。");            Socket socket = serverSocket.accept();            System.out.println("连接成功!");            new Send(socket).start();            new Receive(socket).start();       }catch(Exception e){            e.printStackTrace();       }   }}

创建客户端

class ClientSend extends Thread{    private Socket socket;    public ClientSend(Socket socket){        this.socket = socket;   }    @Override    public void run() {        this.sendMsg();   }        private void sendMsg(){        //创建Scanner对象        try(Scanner scanner = new Scanner(System.in);            //创建向对方输出消息的流对象            PrintWriter pw = new PrintWriter(this.socket.getOutputStream());)            {            while(true){                String msg = scanner.nextLine();                pw.println(msg);                pw.flush();           }       }catch(Exception e){            e.printStackTrace();       }   }}class ClientReceive extends Thread{    private Socket socket;    public ClientReceive(Socket socket){        this.socket = socket;   }    @Override    public void run() {        this.receiveMsg();   }        private void receiveMsg(){        //创建用于接收对方发送消息的流对象        try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));){            while(true){                String msg = br.readLine();                System.out.println("他说:"+msg);           }       }catch(Exception e){            e.printStackTrace();       }   }}public class ChatSocketClient {    public static void main(String[] args) {        try {            Socket socket = new Socket("127.0.0.1", 8888);            System.out.println("连接成功!");            new ClientSend(socket).start();            new ClientReceive(socket).start();       }catch(Exception e){            e.printStackTrace();       }   }}

优化点对点聊天应用

class Send extends Thread{    private Socket socket;    private Scanner scanner;    public Send(Socket socket,Scanner scanner){        this.socket = socket;        this.scanner = scanner;}    @Override    public void run() {        this.sendMsg();   }        private void sendMsg(){        //创建向对方输出消息的流对象        try(PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){                        while(true){                String msg = scanner.nextLine();                pw.println(msg);                pw.flush();           }       }catch(Exception e){            e.printStackTrace();       }   }}class Receive extends Thread{    private Socket socket;  public Receive(Socket socket){        this.socket = socket;   }    @Override    public void run() {        this.receiveMsg();   }        private void receiveMsg(){        //创建用于接收对方发送消息的流对象        try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()))){            while(true){                String msg = br.readLine();                System.out.println("他说:"+msg);           }       }catch(Exception e){            e.printStackTrace();       }   }}public class GoodTCP {    public static void main(String[] args)      {        Scanner scanner = null;        ServerSocket serverSocket = null;        Socket socket = null;        try{            scanner = new Scanner(System.in);            System.out.println("请输入:server, 或者:,");            String str = scanner.nextLine();            String[] arr = str.split(",");            if("server".equals(arr[0])){                //启动服务端                System.out.println("TCP Server Listen at "+arr[1]+" .....");                serverSocket = new ServerSocket(Integer.parseInt(arr[1]));                socket = serverSocket.accept();                System.out.println("连接成功!");           }else{                //启动客户端                socket = new Socket(arr[0],Integer.parseInt(arr[1]));                System.out.println("连接成功!");           }            //启动发送消息的线程            new Send(socket,scanner).start();            //启动接收消息的线程         }catch(Exception e){            e.printStackTrace();       }finally{            if(serverSocket != null){                try {                    serverSocket.close();               } catch (IOException e) {                    e.printStackTrace();               }           }       }   }}

一对多应用

一对多应用设计

各socket对间独立问答,互相间不需要传递信息。

 一对多应答型服务器

class Msg extends Thread{    private Socket socket;    public Msg(Socket socket){        this.socket = socket;   }    @Override    public void run() {        this.msg();   }        private void msg(){        try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));            PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){            while(true){                pw.println(br.readLine()+" [ok]");                pw.flush();           }       }catch(Exception e){            e.printStackTrace();          System.out.println(this.socket.getInetAddress()+" 断线了!");       }   }}public class EchoServer {    public static void main(String[] args) {        try(ServerSocket serverSocket = new ServerSocket(8888)){            //等待多客户端连接            while(true){                Socket socket = serverSocket.accept();                new Msg(socket).start();           }       }catch(Exception e){            e.printStackTrace();       }   }}

一对多聊天服务器

服务器设计

1、服务器的连接设计

2、服务器的线程设计

 创建一对多聊天服务应用

class ChatReceive extends Thread{    private Socket socket;    public ChatReceive(Socket socket){        this.socket =socket;   }    @Override    public void run() {        this.receiveMsg();   }        private void receiveMsg(){        try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()))){            while(true){                String msg = br.readLine();                synchronized ("abc"){                    //把读取到的数据写入公共数据区                    ChatRoomServer.buf=" ["+this.socket.getInetAddress()+"] "+msg;                    //唤醒发送消息的线程对象。                    "abc".notifyAll();               }           }       }catch(Exception e){            e.printStackTrace();       }   }}class ChatSend extends Thread{    private Socket socket;    public ChatSend(Socket socket){        this.socket = socket;   }    @Override    public void run() {        this.sendMsg();   }        private void sendMsg(){        try(PrintWriter  pw = new PrintWriter(this.socket.getOutputStream())){            while(true){                synchronized ("abc"){                    //让发送消息的线程处于等待状态                    "abc".wait();                    //将公共数据区中的消息发送给客户端                    pw.println(ChatRoomServer.buf);                    pw.flush();               }           }       }catch(Exception e){            e.printStackTrace();       }   }}public class ChatRoomServer {    //定义公共数据区    public static String buf;    public static void main(String[] args) {        System.out.println("Chat Server Version 1.0");        System.out.println("Listen at 8888.....");        try(ServerSocket serverSocket = new ServerSocket(8888)){            while(true){                Socket socket = serverSocket.accept();                System.out.println("连接到:"+socket.getInetAddress());                new ChatReceive(socket).start();                new ChatSend(socket).start();           }       }catch(Exception e){            e.printStackTrace();       }   }}

来源地址:https://blog.csdn.net/m0_58719994/article/details/131669344

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

目录