对于即时类应用或者即时类的游戏,HTTP协议很多时候无法满足于我们的需求。这会,Socket对于我们来说就非常实用了。下面是本次学习的笔记。主要分异常类型、交互原理、Socket、ServerSocket、多线程这几个方面阐述。

异常类型
在了解Socket的内容之前,先要了解一下涉及到的一些异常类型。以下四种类型都是继承于IOException,所以很多之后直接弹出IOException即可。
UnkownHostException:主机名字或IP错误
ConnectException:服务器拒绝连接、服务器没有启动、(超出队列数,拒绝连接)
SocketTimeoutException:连接超时
BindException:Socket对象无法与制定的本地IP地址或端口绑定

交互过程
Socket与ServerSocket的交互,下面的图片我觉得已经说的很详细很清楚了。
Socket
构造函数

Socket()

Socket(InetAddress address, int port)throws UnknownHostException, IOException
Socket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException
Socket(String host, int port)throws UnknownHostException,IOException
Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException

除去第一种不带参数的之外,其它构造函数会尝试建立与服务器的连接。如果失败会抛出IOException错误。如果成功,则返回Socket对象。
InetAddress是一个用于记录主机的类,其静态getHostByName(String msg)可以返回一个实例,其静态方法getLocalHost()也可以获得当前主机的IP地址,并返回一个实例。Socket(String host, int port, InetAddress localAddress, int localPort)构造函数的参数分别为目标IP、目标端口、绑定本地IP、绑定本地端口。
Socket方法
getInetAddress();远程服务端的IP地址
getPort();远程服务端的端口
getLocalAddress()本地客户端的IP地址
getLocalPort()本地客户端的端口
getInputStream();获得输入流
getOutStream();获得输出流
值得注意的是,在这些方法里面,最重要的就是getInputStream()和getOutputStream()了。
Socket状态
isClosed();//连接是否已关闭,若关闭,返回true;否则返回false
isConnect();      //如果曾经连接过,返回true;否则返回false
isBound();//如果Socket已经与本地一个端口绑定,返回true;否则返回false
如果要确认Socket的状态是否处于连接中,下面语句是很好的判断方式。
boolean isConnection=socket.isConnected() && !socket.isClosed();   //判断当前是否处于连接

半关闭Socket
很多时候,我们并不知道在获得的输入流里面到底读多长才结束。下面是一些比较普遍的方法:
  • 自定义标识符(譬如下面的例子,当受到“bye”字符串的时候,关闭Socket)
  • 告知读取长度(有些自定义协议的,固定前几个字节表示读取的长度的)
  • 读完所有数据
  • 当Socket调用close的时候关闭的时候,关闭其输入输出流
 
ServerSocket
构造函数
ServerSocket()throws IOException
ServerSocket(int port)throws IOException
ServerSocket(int port, int backlog)throws IOException
ServerSocket(int port, int backlog, InetAddress bindAddr)throws IOException
 
注意点:
1. port服务端要监听的端口;backlog客户端连接请求的队列长度;bindAddr服务端绑定IP
2. 如果端口被占用或者没有权限使用某些端口会抛出BindException错误。譬如1~1023的端口需要管理员才拥有权限绑定。
3. 如果设置端口为0,则系统会自动为其分配一个端口;
4. bindAddr用于绑定服务器IP,为什么会有这样的设置呢,譬如有些机器有多个网卡。
5. ServerSocket一旦绑定了监听端口,就无法更改。ServerSocket()可以实现在绑定端口前设置其他的参数。
 
单线程的ServerSocket例子
public void service(){while(true){Socket socket=null;try{socket=serverSocket.accept();//从连接队列中取出一个连接,如果没有则等待System.out.println("新增连接:"+socket.getInetAddress()+":"+socket.getPort());...//接收和发送数据}catch(IOException e){e.printStackTrace();}finally{try{if(socket!=null) socket.close();//与一个客户端通信结束后,要关闭Socket}catch(IOException e){e.printStackTrace();}}}
}

多线程的ServerSocket
多线程的好处不用多说,而且大多数的场景都是多线程的,无论是我们的即时类游戏还是IM,多线程的需求都是必须的。下面说说实现方式:
  • 主线程会循环执行ServerSocket.accept();
  • 当拿到客户端连接请求的时候,就会将Socket对象传递给多线程,让多线程去执行具体的操作;
实现多线程的方法要么继承Thread类,要么实现Runnable接口。当然也可以使用线程池,但实现的本质都是差不多的。
这里举例:
下面代码为服务器的主线程。为每个客户分配一个工作线程:

public void service(){while(true){Socket socket=null;try{socket=serverSocket.accept();                        //主线程获取客户端连接Thread workThread=new Thread(new Handler(socket));    //创建线程workThread.start();                                    //启动线程}catch(Exception e){e.printStackTrace();}}
}

当然这里的重点在于如何实现Handler这个类。Handler需要实现Runnable接口:
class Handler implements Runnable{private Socket socket;public Handler(Socket socket){this.socket=socket;}public void run(){try{System.out.println("新连接:"+socket.getInetAddress()+":"+socket.getPort());Thread.sleep(10000);}catch(Exception e){e.printStackTrace();}finally{try{System.out.println("关闭连接:"+socket.getInetAddress()+":"+socket.getPort());if(socket!=null)socket.close();}catch(IOException e){e.printStackTrace();}}}
}

当然是先多线程还有其它的方式,譬如线程池,或者JVM自带的线程池都可以。这里就不说明了。

[Java]Socket和ServerSocket学习笔记相关推荐

  1. JAVA基础与高级学习笔记

    JAVA基础与高级学习笔记 /记录java基础与高级,除了较简单的内容,没有必要记录的没有记录外,其余的都记录了/ java初学者看这一篇就够了,全文 6万+ 字. JAVA基础 java会出现内存溢 ...

  2. 零基础学习Java开发,这些学习笔记送给你

    因为Java具备很多特点,并且在企业中被广泛应用为此很多小伙伴选择学习Java基础开发,但是零基础学习Java技术开发需要我们制定Java学习路线图对于我们之后的学习会非常有帮助. 零基础学习Java ...

  3. Java 8 函数式编程学习笔记

    Java 8 函数式编程学习笔记 @(JAVASE)[java8, 函数式编程, lambda] Java 8 函数式编程学习笔记 参考内容 Java 8中重要的函数接口 扩展函数接口 常用的流操作 ...

  4. 【Java】函数式编程学习笔记——Stream流

    学习视频:https://www.bilibili.com/video/BV1Gh41187uR?p=1 (1)[Java]函数式编程学习笔记--Lambda表达式 (2)[Java]函数式编程学习笔 ...

  5. java 编程思想 多线程学习笔记

    java 编程思想 多线程学习笔记 一.如何创建多线程? 1.继承 java.lang.Thread 类 2.实现 java.lang.Runnable 接口 3.Callable接口 总之,在任何线 ...

  6. 第10课:底实战详解使用Java开发Spark程序学习笔记

    第10课:底实战详解使用Java开发Spark程序学习笔记 本期内容: 1. 为什么要使用Java? 2. 使用Java开发Spark实战 3. 使用Java开发Spark的Local和Cluster ...

  7. Java并发编程艺术学习笔记(五)

    Java并发编程艺术学习笔记(五) Java并发容器和框架 Java为开发者也提供了许多开发容器和框架,可以从每节的原理分析来学习其中精妙的并发程序. 一.ConcurrentHashMap的实现原理 ...

  8. 《Java编程思想》学习笔记【一对象导论】

    重头学习Java,大一没怎么学,大二上课也没听.(流下不学无术的眼泪) 所有编程语言都提供抽象机制,我们所能解决的问题的复杂性直接取决于抽象的类型和质量. 汇编语言是对底层机器的轻微抽象," ...

  9. Java之GUI编程学习笔记六 —— AWT相关(画笔paint、鼠标监听事件、模拟画图工具)

    Java之GUI编程学习笔记六 -- AWT相关(画笔paint) 参考教程B站狂神https://www.bilibili.com/video/BV1DJ411B75F 了解paint Frame自 ...

最新文章

  1. 第五周项目一-三角形类雏形(5)
  2. linux 编写完程序吗,linux下编写C++程序
  3. FreeTextBox 3.1.6 的实践总结和几个问题
  4. 有函数就可以实现面向对象
  5. python输出字符_python输出字符
  6. MySQL命令行客户端(一)客户端选项
  7. 树莓派 使用xbox360手柄
  8. C++之文件批量改名
  9. tensorflow2.X tf.data.Dataset详解
  10. java resource文件_利用java如何实现读取resource目录下文件
  11. Proteus 8 Professional安装教程
  12. 2019年,IT行业发展前景
  13. 设计实现信用卡用户定时还款功能
  14. android微信怎么建群,微信群空间是什么?如何创建微信群空间?
  15. 设备树学习(四、内核head.S对uboot传参的处理)
  16. iOS学习—让View从下面弹出
  17. Rabbitmq 和erlang 安装成功但是网面访问不了
  18. 字节跳动技术中台前端日常实习一面 21/11/19
  19. kabeja导出DXF为其他格式
  20. ubtunu打开firefox_虚拟机Ubuntu下安装Firefox浏览器

热门文章

  1. Linux下的字符界面扫雷游戏
  2. Spring源码学习笔记:经典设计模式之代理模式
  3. [Java] 蓝桥杯ALGO-13 算法训练 拦截导弹
  4. [Python] L1-018. 大笨钟-PAT团体程序设计天梯赛GPLT
  5. 1085. Perfect Sequence (25)-PAT甲级真题
  6. 创建对象、原型、原型链
  7. 简单易用的APP制作软件,KM盒子V6.3版发布
  8. css3——新盒子定义box-sizing
  9. Unity3d面向英特尔 x86 平台的 Unity* 优化指南: 第 2 部分
  10. 在jquery的ajax方法中的success中使用return要注意的问题