Java入门系列-24-实现网络通信

简介:

互联网上那么多设备,java 是如何与其他设备通信的呢?这次的内容是网络通信的基础,有了它咱们才能上网页、玩游戏、视频聊天。

Socket 客户端套接字

Socket 客户端套接字,用于连接互联网提供服务的设备。

Socket 构造方法

构造方法 说明
Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字
Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号

常用方法

方法名称 说明
getOutputStream() 返回此套接字的输出流
getInputStream() 返回此套接字的输入流

下面示例模拟了一个 HTTP 请求

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class TestSocket {

    public static void main(String[] args) {
        
        //创建套接字
        try(Socket s=new Socket("www.baidu.com", 80);){
            //创建向服务器发送数据的输出流
            OutputStream os=s.getOutputStream();
            StringBuffer sb=new StringBuffer();
            //HTTP协议 请求报文
            sb.append("GET / HTTP/1.1\r\n");
            sb.append("Host: www.baidu.com:80\r\n");
            sb.append("Connection: Keep-Alive\r\n");
            //这里一定要一个回车换行,表示消息头完,不然服务器会等待
            sb.append("\r\n");
            //发送
            os.write(sb.toString().getBytes());
            //获取服务器相应内容 
            InputStream is=s.getInputStream();
            //通过输入流创建扫描器,并指定编码为utf-8防止中文乱码
            Scanner scanner=new Scanner(is,"utf-8");
            
            while(scanner.hasNextLine()) {
                String line=scanner.nextLine();
                System.out.println(line);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
            System.out.println("未知主机");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常");
        }
    }
}

ServerSocket

ServerSocket:实现服务器套接字,服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TestServerSocket {

    public static void main(String[] args) {
        //创建 ServerSocket 监听1666端口
        try(ServerSocket server=new ServerSocket(1666)){
            //阻塞方法,当有客户端连入,获取客户端Socket
            try(Socket client=server.accept()){
                //获取客户端发送的数据
                InputStream is=client.getInputStream();
                //获取向客户端发送数据的流
                OutputStream os=client.getOutputStream();
                //通过输入流创建扫描器
                try(Scanner scanner=new Scanner(is)){
                    
                    PrintWriter pw=new PrintWriter(os,true/*自动刷新*/);
                    //向客户端发送消息
                    pw.println("Hello,enter bye to exit.");
                    boolean done=false;
                    //客户端有输入数据并且没有发送 bye 
                    while(!done&&scanner.hasNextLine()) {
                        //接收客户端发送的数据
                        String line=scanner.nextLine();
                        //将客户端发送的数据发回客户端
                        pw.println("Echo:"+line);
                        //如果客户端输入bye 结束通信
                        if(line.trim().equalsIgnoreCase("bye")) {done=true;}
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

测试方式:
在DOS 中输入命令:telnet 127.0.0.1 1666

telnet 不是内部或外部命令的读者,需要在 Windows 功能中启用 Telnet 客户端。

上面的代码如果有多个客户端连入就不行了,如果希望服务能被多个客户端连接,可以使用线程。

多线程服务器

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TestMultiServerSocket {

    public static void main(String[] args) {
        //创建 ServerSocket 监听 1666端口
        try(ServerSocket server=new ServerSocket(1666)){
            while(true) {
                //accept() 是一个阻塞方法
                Socket client=server.accept();
                InputStream is=client.getInputStream();
                OutputStream os=client.getOutputStream();
                //开启新的线程处理,传入当前客户端
                Thread t=new Thread(new ThreadEchoHandler(client));
                t.start();                
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class ThreadEchoHandler implements Runnable{
    private Socket socket=null;

    public ThreadEchoHandler(Socket socket) {
        this.socket=socket;
    }
    @Override
    public void run() {
        try {
            InputStream is=socket.getInputStream();
            OutputStream os=socket.getOutputStream();
            try(Scanner scanner=new Scanner(is)){
                PrintWriter pw=new PrintWriter(os,true);
                pw.println("Hello,enter bye to exit.");
                boolean done=false;
                while(!done&&scanner.hasNextLine()) {
                    String line=scanner.nextLine();
                    pw.println("Echo:"+line);
                    if(line.trim().equalsIgnoreCase("bye")) {done=true;}
                }
            }
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

URLConnection

抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。

Socket 可以默认任意类型的网络通信,URLConnection 更适合 HTTP 请求,使用 URLConnection 进行HTTP操作更方便,模拟请求报文,获取响应报文和内容。

URLConnection 常用方法

方法 说明
connect() 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)
getContentEncoding() 返回 content-encoding 头字段的值
getContentType() 返回 content-type 头字段的值
getHeaderFields() 返回头字段的不可修改的 Map
getInputStream() 返回从此打开的连接读取的输入流
setRequestProperty(String key, String value) 设置一般请求属性

获取 URLConnection 需要先创建 URL 对象:
URL url=new URL(host);

使用 URLConnection 获取网页的内容

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;

public class TestURLConnection {
    public static void main(String[] args) {
        
        try {
            //创建URL对象
            URL url=new URL("http://www.baidu.com");
            //创建 URLConnection对象
            URLConnection connection=url.openConnection();
            //设置请求属性
            //connection.setRequestProperty("", "");
            //连接
            connection.connect();
            //获取输入流
            InputStream is=connection.getInputStream();
            //通过输入流构建一个扫描器
            Scanner scanner=new Scanner(is,"utf-8");
            while(scanner.hasNextLine()) {
                String line=scanner.nextLine();
                System.out.println(line);
            }
            System.out.println("===响应头===");
            Map<String,List<String>> headers=connection.getHeaderFields();
            for (Entry<String, List<String>> entry: headers.entrySet()) {
                String key=entry.getKey();
                System.out.print(key+":");
                for (String string : entry.getValue()) {
                    System.out.print(string);
                }
                System.out.println();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
相关文章
|
13天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:理解神经网络与反向传播算法
【9月更文挑战第20天】本文将深入浅出地介绍深度学习中的基石—神经网络,以及背后的魔法—反向传播算法。我们将通过直观的例子和简单的数学公式,带你领略这一技术的魅力。无论你是编程新手,还是有一定基础的开发者,这篇文章都将为你打开深度学习的大门,让你对神经网络的工作原理有一个清晰的认识。
|
1月前
|
监控 安全 数据安全/隐私保护
智能家居安全入门:保护你的网络家园
本文旨在为初学者提供一份简明扼要的指南,介绍如何保护自己的智能家居设备免受网络攻击。通过分析智能家居系统常见的安全漏洞,并提供实用的防御策略,帮助读者建立起一道坚固的数字防线。
|
7天前
|
域名解析 网络协议 应用服务中间件
网络编程入门如此简单(四):一文搞懂localhost和127.0.0.1
本文将以网络编程入门者视角,言简意赅地为你请清楚localhost和127.0.0.1的关系及区别等。
16 2
网络编程入门如此简单(四):一文搞懂localhost和127.0.0.1
|
3天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的卷积神经网络(CNN)入门与实践
【8月更文挑战第62天】本文以浅显易懂的方式介绍了深度学习领域中的核心技术之一——卷积神经网络(CNN)。文章通过生动的比喻和直观的图示,逐步揭示了CNN的工作原理和应用场景。同时,结合具体的代码示例,引导读者从零开始构建一个简单的CNN模型,实现对图像数据的分类任务。无论你是深度学习的初学者还是希望巩固理解的开发者,这篇文章都将为你打开一扇通往深度学习世界的大门。
|
10天前
|
Java 程序员 UED
Java中的异常处理:从入门到精通
【9月更文挑战第23天】在Java编程的世界中,异常是程序执行过程中不可避免的事件,它们可能会中断正常的流程并导致程序崩溃。本文将通过浅显易懂的方式,引导你理解Java异常处理的基本概念和高级技巧,帮助你编写更健壮、更可靠的代码。我们将一起探索如何捕获和处理异常,以及如何使用自定义异常来增强程序的逻辑和用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的见解和实用的技巧。
28 4
|
14天前
|
机器学习/深度学习 人工智能 算法
深度学习中的卷积神经网络(CNN)入门与实践
【9月更文挑战第19天】在这篇文章中,我们将探索深度学习的一个重要分支——卷积神经网络(CNN)。从基础概念出发,逐步深入到CNN的工作原理和实际应用。文章旨在为初学者提供一个清晰的学习路径,并分享一些实用的编程技巧,帮助读者快速上手实践CNN项目。
|
19天前
|
机器学习/深度学习 人工智能 TensorFlow
深度学习入门:理解卷积神经网络(CNN)
【9月更文挑战第14天】本文旨在为初学者提供一个关于卷积神经网络(CNN)的直观理解,通过简单的语言和比喻来揭示这一深度学习模型如何识别图像。我们将一起探索CNN的基本组成,包括卷积层、激活函数、池化层和全连接层,并了解它们如何协同工作以实现图像分类任务。文章末尾将给出一个简单的代码示例,帮助读者更好地理解CNN的工作原理。
38 7
|
2月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
82 6
|
22天前
|
Java 程序员
Java中的异常处理:从入门到精通
在Java编程的世界中,异常处理是保持程序稳定性和可靠性的关键。本文将通过一个独特的视角—把异常处理比作一场“捉迷藏”游戏—来探讨如何在Java中有效管理异常。我们将一起学习如何识别、捕捉以及处理可能出现的异常,确保你的程序即使在面对不可预见的错误时也能优雅地运行。准备好了吗?让我们开始这场寻找并解决Java异常的冒险吧!
|
24天前
|
机器学习/深度学习 人工智能 TensorFlow
神经网络入门到精通:Python带你搭建AI思维,解锁机器学习的无限可能
【9月更文挑战第10天】神经网络是开启人工智能大门的钥匙,不仅是一种技术,更是模仿人脑思考的奇迹。本文从基础概念入手,通过Python和TensorFlow搭建手写数字识别的神经网络,逐步解析数据加载、模型定义、训练及评估的全过程。随着学习深入,我们将探索深度神经网络、卷积神经网络等高级话题,并掌握优化模型性能的方法。通过不断实践,你将能构建自己的AI系统,解锁机器学习的无限潜能。
18 0
下一篇
无影云桌面