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

Socket 客户端套接字

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

Socket 构造方法

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

常用方法

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

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

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.Socket;
  5. import java.net.UnknownHostException;
  6. import java.util.Scanner;
  7. public class TestSocket {
  8. public static void main(String[] args) {
  9. //创建套接字
  10. try(Socket s=new Socket("www.baidu.com", 80);){
  11. //创建向服务器发送数据的输出流
  12. OutputStream os=s.getOutputStream();
  13. StringBuffer sb=new StringBuffer();
  14. //HTTP协议 请求报文
  15. sb.append("GET / HTTP/1.1\r\n");
  16. sb.append("Host: www.baidu.com:80\r\n");
  17. sb.append("Connection: Keep-Alive\r\n");
  18. //这里一定要一个回车换行,表示消息头完,不然服务器会等待
  19. sb.append("\r\n");
  20. //发送
  21. os.write(sb.toString().getBytes());
  22. //获取服务器相应内容
  23. InputStream is=s.getInputStream();
  24. //通过输入流创建扫描器,并指定编码为utf-8防止中文乱码
  25. Scanner scanner=new Scanner(is,"utf-8");
  26. while(scanner.hasNextLine()) {
  27. String line=scanner.nextLine();
  28. System.out.println(line);
  29. }
  30. } catch (UnknownHostException e) {
  31. e.printStackTrace();
  32. System.out.println("未知主机");
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. System.out.println("IO异常");
  36. }
  37. }
  38. }

ServerSocket

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

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.io.PrintWriter;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. import java.util.Scanner;
  8. public class TestServerSocket {
  9. public static void main(String[] args) {
  10. //创建 ServerSocket 监听1666端口
  11. try(ServerSocket server=new ServerSocket(1666)){
  12. //阻塞方法,当有客户端连入,获取客户端Socket
  13. try(Socket client=server.accept()){
  14. //获取客户端发送的数据
  15. InputStream is=client.getInputStream();
  16. //获取向客户端发送数据的流
  17. OutputStream os=client.getOutputStream();
  18. //通过输入流创建扫描器
  19. try(Scanner scanner=new Scanner(is)){
  20. PrintWriter pw=new PrintWriter(os,true/*自动刷新*/);
  21. //向客户端发送消息
  22. pw.println("Hello,enter bye to exit.");
  23. boolean done=false;
  24. //客户端有输入数据并且没有发送 bye
  25. while(!done&&scanner.hasNextLine()) {
  26. //接收客户端发送的数据
  27. String line=scanner.nextLine();
  28. //将客户端发送的数据发回客户端
  29. pw.println("Echo:"+line);
  30. //如果客户端输入bye 结束通信
  31. if(line.trim().equalsIgnoreCase("bye")) {done=true;}
  32. }
  33. }
  34. }
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. }

测试方式:

在DOS 中输入命令:telnet 127.0.0.1 1666

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

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

多线程服务器

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.io.PrintWriter;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. import java.util.Scanner;
  8. public class TestMultiServerSocket {
  9. public static void main(String[] args) {
  10. //创建 ServerSocket 监听 1666端口
  11. try(ServerSocket server=new ServerSocket(1666)){
  12. while(true) {
  13. //accept() 是一个阻塞方法
  14. Socket client=server.accept();
  15. InputStream is=client.getInputStream();
  16. OutputStream os=client.getOutputStream();
  17. //开启新的线程处理,传入当前客户端
  18. Thread t=new Thread(new ThreadEchoHandler(client));
  19. t.start();
  20. }
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. class ThreadEchoHandler implements Runnable{
  27. private Socket socket=null;
  28. public ThreadEchoHandler(Socket socket) {
  29. this.socket=socket;
  30. }
  31. @Override
  32. public void run() {
  33. try {
  34. InputStream is=socket.getInputStream();
  35. OutputStream os=socket.getOutputStream();
  36. try(Scanner scanner=new Scanner(is)){
  37. PrintWriter pw=new PrintWriter(os,true);
  38. pw.println("Hello,enter bye to exit.");
  39. boolean done=false;
  40. while(!done&&scanner.hasNextLine()) {
  41. String line=scanner.nextLine();
  42. pw.println("Echo:"+line);
  43. if(line.trim().equalsIgnoreCase("bye")) {done=true;}
  44. }
  45. }
  46. socket.close();
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }

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 获取网页的内容

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.net.HttpURLConnection;
  4. import java.net.MalformedURLException;
  5. import java.net.URL;
  6. import java.net.URLConnection;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Map.Entry;
  10. import java.util.Scanner;
  11. public class TestURLConnection {
  12. public static void main(String[] args) {
  13. try {
  14. //创建URL对象
  15. URL url=new URL("http://www.baidu.com");
  16. //创建 URLConnection对象
  17. URLConnection connection=url.openConnection();
  18. //设置请求属性
  19. //connection.setRequestProperty("", "");
  20. //连接
  21. connection.connect();
  22. //获取输入流
  23. InputStream is=connection.getInputStream();
  24. //通过输入流构建一个扫描器
  25. Scanner scanner=new Scanner(is,"utf-8");
  26. while(scanner.hasNextLine()) {
  27. String line=scanner.nextLine();
  28. System.out.println(line);
  29. }
  30. System.out.println("===响应头===");
  31. Map<String,List<String>> headers=connection.getHeaderFields();
  32. for (Entry<String, List<String>> entry: headers.entrySet()) {
  33. String key=entry.getKey();
  34. System.out.print(key+":");
  35. for (String string : entry.getValue()) {
  36. System.out.print(string);
  37. }
  38. System.out.println();
  39. }
  40. } catch (MalformedURLException e) {
  41. e.printStackTrace();
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }

Java入门系列-24-实现网络通信的更多相关文章

  1. java io系列24之 BufferedWriter(字符缓冲输出流)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_24.html 更多内容请参考:java io系列01之 "目录" Buffere ...

  2. Java入门系列-26-JDBC

    认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...

  3. Java入门系列-19-泛型集合

    集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...

  4. Java入门系列-25-NIO(实现非阻塞网络通信)

    还记得之前介绍NIO时对比传统IO的一大特点吗?就是NIO是非阻塞式的,这篇文章带大家来看一下非阻塞的网络操作. 补充:以数组的形式使用缓冲区 package testnio; import java ...

  5. Java入门系列:实例讲解ArrayList用法

    本文通过实例讲解Java中如何使用ArrayList类. Java.util.ArrayList类是一个动态数组类型,也就是说,ArrayList对象既有数组的特征,也有链表的特征.可以随时从链表中添 ...

  6. Java入门系列之hashCode和equals(十二)

    前言 前面两节内容我们详细讲解了Hashtable算法和源码分析,针对散列函数始终逃脱不掉hashCode的计算,本节我们将详细分析hashCode和equals,同时您将会看到本节内容是从<E ...

  7. Java入门系列之包装类(四)

    前言 上一节我们讲解了StringBuilder VS StringBuffer以及二者区别,本节我们来讲解包装类. 包装类 我们知道在Java中有8中基本数据类型,分为数值类型:byte.short ...

  8. Java入门系列之字符串创建方式、判断相等(一)

    前言 陆续从0开始学习Java出于多掌握一门语言以后的路也会更宽,.NET和Java兼顾,虽然路还很艰难,但事在人为.由于Java和C#语法相似,所以关于一些很基础的内容不会再重头讲,Java系列中所 ...

  9. Java入门系列之重写

    前言 关于所有Java系列文章面向有一定基础的童鞋,所写每一篇希望有一定含金量,有些内容可能会从Java整个语法全局考虑穿插后续要讲解的内容以成系统,若不理解,请看完后再学习.上一节我们讲解完了fin ...

随机推荐

  1. ifstat命令行统计网络流量

      下载 ifstat ,  http://gael.roualland.free.fr/ifstat/ifstat-1.1.tar.gz   tar xzvf ifstat-1.1.tar.gz   ...

  2. 对路径“c:\windows\system32\inetsrv\syslog”的访问被拒绝。

    win7 64 系统,在调试wcf的时候,出了这个错误,当时感觉iis的权限不够,iis搞了好长时间没解决.最后改了用到的应用程序池中的标识.标识改成 localSytem,之后问题解决. IIS-- ...

  3. C# Email 发送邮件,对方打开通知你

    直接上代码: //回执地址 var Receipt = "填写你需要回执的地址"; //实例化两个必要的 MailMessage mail = new MailMessage(); ...

  4. 「JXOI 2018」 排序问题

    题目链接 戳我 \(Solution\) \(50\ pts\) 我们来看一下题目,可以很容易的写出来答案的式子: \[\frac{(n+m)!}{a_1!a_2!...a_{tot}!}\] \(a ...

  5. tail()和head()

    pandas 里的tail() 函数,读取后几行. head() dataframe.head():前五行 显示某一列的前五行,两种方法: 或者:

  6. OCP 11g认证052考试最新题库(带答案)-带38题

    38.Which three are true about the Automatic Database Diagnostic Monitor (ADDM)? A) Its findings are ...

  7. java 线程 获取当前线程

    java 线程 获取当前线程 Thread th=Thread.currentThread(); System.out.println("Tread name:"+th.getNa ...

  8. Alluxio学习

    介绍 Alluxio(之前名为Tachyon)是世界上第一个以内存为中心的虚拟的分布式存储系统.它统一了数据访问的方式,为上层计算框架和底层存储系统构建了桥梁.应用只需要连接Alluxio即可访问存储 ...

  9. SD与SE的关系,以及异常值

    很多刚进入实验室的同学对实验数据的标准差(SD)与标准误(SE)的含义搞不清,不知道自己的数据报告到底该用SD还是SE.这里对这两个概念进行一些介绍. 标准差(SD)强调raw data的Variat ...

  10. Angular material mat-icon 资源参考_File

    ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...