socket的原理和使用

淩亂°似流年 2022-06-11 00:56 255阅读 0赞

前言

  • Socket的使用在 Android网络编程中非常重要
  • 今天我将带大家全面了解 Socket 及 其使用方法
  1. --------------------

目录

目录


1.网络基础

1.1 计算机网络分层

计算机网络分为五层:物理层、数据链路层、网络层、运输层、应用层

计算机网络

其中:

  • 网络层:负责根据IP找到目的地址的主机
  • 运输层:通过端口把数据传到目的主机的目的进程,来实现进程与进程之间的通信

1.2 端口号(PORT)

端口号规定为16位,即允许一个IP主机有2的16次方65535个不同的端口。其中:

  • 0~1023:分配给系统的端口号
  1. > 我们不可以乱用
  • 1024~49151:登记端口号,主要是让第三方应用使用

    但是必须在IANA(互联网数字分配机构)按照规定手续登记,

  • 49152~65535:短暂端口号,是留给客户进程选择暂时使用,一个进程使用完就可以供其他进程使用。

在Socket使用时,可以用1024~65535的端口号

1.3 C/S结构

  • 定义:即客户端/服务器结构,是软件系统体系结构
  • 作用:充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。
  1. > Socket正是使用这种结构建立连接的,一个套接字接客户端,一个套接字接服务器。

如图: Socket架构
可以看出,Socket的使用可以基于TCP或者UDP协议。

1.4 TCP协议

  • 定义:Transmission Control Protocol,即传输控制协议,是一种传输层通信协议
  1. > 基于TCP的应用层协议有FTPTelnetSMTPHTTPPOP3DNS
  • 特点:面向连接、面向字节流、全双工通信、可靠

    • 面向连接:指的是要使用TCP传输数据,必须先建立TCP连接,传输完成后释放连接,就像打电话一样必须先拨号建立一条连接,打完后挂机释放连接。
    • 全双工通信:即一旦建立了TCP连接,通信双方可以在任何时候都能发送数据。
    • 可靠的:指的是通过TCP连接传送的数据,无差错,不丢失,不重复,并且按序到达。
    • 面向字节流:流,指的是流入到进程或从进程流出的字符序列。简单来说,虽然有时候要传输的数据流太大,TCP报文长度有限制,不能一次传输完,要把它分为好几个数据块,但是由于可靠性保证,接收方可以按顺序接收数据块然后重新组成分块之前的数据流,所以TCP看起来就像直接互相传输字节流一样,面向字节流。
  • TCP建立连接
    必须进行三次握手:若A要与B进行连接,则必须
  1. * 第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1Sequence Numberx;然后,客户端进入SYN\_SEND状态,等待服务器的确认。即A发送信息给B
  2. * 第二次握手:服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认。即B收到连接信息后向A返回确认信息
  3. * 第三次握手:客户端收到服务器的(SYN+ACK)报文段,并向服务器发送ACK报文段。即A收到确认信息后再次向B返回确认连接信息
  4. > 此时,A告诉自己上层连接建立;B收到连接信息后告诉上层连接建立。

TCP三次握手

这样就完成TCP三次握手 = 一条TCP连接建立完成 = 可以开始发送数据

  1. 三次握手期间任何一次未收到对面回复都要重发。
  2. 最后一个确认报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态。

为什么TCP建立连接需要三次握手?

答:防止服务器端因为接收了早已失效的连接请求报文从而一直等待客户端请求,从而浪费资源

  • “已失效的连接请求报文段”的产生在这样一种情况下:Client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。
  • 这是一个早已失效的报文段。但Server收到此失效的连接请求报文段后,就误认为是Client再次发出的一个新的连接请求。
  • 于是就向Client发出确认报文段,同意建立连接。
  • 假设不采用“三次握手”:只要Server发出确认,新的连接就建立了。
  • 由于现在Client并没有发出建立连接的请求,因此不会向Server发送数据。
  • 但Server却以为新的运输连接已经建立,并一直等待Client发来数据。>- 这样,Server的资源就白白浪费掉了。

采用“三次握手”的办法可以防止上述现象发生:

  • Client不会向Server的确认发出确认
  • Server由于收不到确认,就知道Client并没有要求建立连接
  • 所以Server不会等待Client发送数据,资源就没有被浪费
  • TCP释放连接
    TCP释放连接需要四次挥手过程,现在假设A主动释放连接:(数据传输结束后,通信的双方都可释放连接)

    • 第一次挥手:A发送释放信息到B;(发出去之后,A->B发送数据这条路径就断了)
    • 第二次挥手:B收到A的释放信息之后,回复确认释放的信息:我同意你的释放连接请求
    • 第三次挥手:B发送“请求释放连接“信息给A
    • 第四次挥手:A收到B发送的信息后向B发送确认释放信息:我同意你的释放连接请求

      B收到确认信息后就会正式关闭连接;
      A等待2MSL后依然没有收到回复,则证明B端已正常关闭,于是A关闭连接

TCp四次握手

为什么TCP释放连接需要四次挥手?

为了保证双方都能通知对方“需要释放连接”,即在释放连接后都无法接收或发送消息给对方

  • 需要明确的是:TCP是全双工模式,这意味着是双向都可以发送、接收的
  • 释放连接的定义是:双方都无法接收或发送消息给对方,是双向的
  • 当主机1发出“释放连接请求”(FIN报文段)时,只是表示主机1已经没有数据要发送 / 数据已经全部发送完毕;
  1. > 但是,这个时候主机1还是可以接受来自主机2的数据。
  • 当主机2返回“确认释放连接”信息(ACK报文段)时,表示它已经知道主机1没有数据发送了
    但此时主机2还是可以发送数据给主机1
  • 当主机2也发送了FIN报文段时,即告诉主机1我也没有数据要发送了
    此时,主机1和2已经无法进行通信:主机1无法发送数据给主机2,主机2也无法发送数据给主机1,此时,TCP的连接才算释放
1.5 UDP协议
  • 定义:User Datagram Protocol,即用户数据报协议,是一种传输层通信协议。

    基于UDP的应用层协议有TFTP、SNMP与DNS。

  • 特点:无连接的、不可靠的、面向报文、没有拥塞控制

    • 无连接的:和TCP要建立连接不同,UDP传输数据不需要建立连接,就像写信,在信封写上收信人名称、地址就可以交给邮局发送了,至于能不能送到,就要看邮局的送信能力和送信过程的困难程度了。
    • 不可靠的:因为UDP发出去的数据包发出去就不管了,不管它会不会到达,所以很可能会出现丢包现象,使传输的数据出错。
    • 面向报文:数据报文,就相当于一个数据包,应用层交给UDP多大的数据包,UDP就照样发送,不会像TCP那样拆分。
    • 没有拥塞控制:拥塞,是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿,即出现死锁现象,就像交通堵塞一样。TCP建立连接后如果发送的数据因为信道质量的原因不能到达目的地,它会不断重发,有可能导致越来越塞,所以需要一个复杂的原理来控制拥塞。而UDP就没有这个烦恼,发出去就不管了。
  • 应用场景
    很多的实时应用(如IP电话、实时视频会议、某些多人同时在线游戏等)要求源主机以很定的速率发送数据,并且允许在网络发生拥塞时候丢失一些数据,但是要求不能有太大的延时,UDP就刚好适合这种要求。所以说,只有不适合的技术,没有真正没用的技术。
1.6 HTTP协议

详情请看我写的另外一篇文章你需要了解的HTTP知识都在这里了!


2. Socket定义

  • 即套接字,是一个对 TCP / IP协议进行封装 的编程调用接口(API)

    1. 即通过Socket,我们才能在Andorid平台上通过 TCP/IP协议进行开发
    2. Socket不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)
  • 成对出现,一对套接字:

    Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)}

  1. 1
  2. 1

3. 原理

Socket的使用类型主要有两种:

  • 流套接字(streamsocket) :基于 TCP协议,采用 流的方式 提供可靠的字节流服务
  • 数据报套接字(datagramsocket):基于 UDP协议,采用 数据报文 提供数据打包发送的服务

具体原理图如下:

原理图

4. Socket 与 Http 对比

  • Socket属于传输层,因为 TCP / IP协议属于传输层,解决的是数据如何在网络中传输的问题
  • HTTP协议 属于 应用层,解决的是如何包装数据

由于二者不属于同一层面,所以本来是没有可比性的。但随着发展,默认的Http里封装了下面几层的使用,所以才会出现Socket & HTTP协议的对比:(主要是工作方式的不同):

  • Http:采用 请求—响应 方式。

    1. 即建立网络连接后,当 客户端 向 服务器 发送请求后,服务器端才能向客户端返回数据。
    2. 可理解为:是客户端有需要才进行通信
  • Socket:采用 服务器主动发送数据 的方式

    1. 即建立网络连接后,服务器可主动发送消息给客户端,而不需要由客户端向服务器发送请求
    2. 可理解为:是服务器端有需要才进行通信

5. 使用步骤

  • Socket可基于TCP或者UDP协议,但TCP更加常用
  • 所以下面的使用步骤 & 实例的Socket将基于TCP协议

    // 步骤1:创建客户端 & 服务器的连接

    1. // 创建Socket对象 & 指定服务端的IP及端口号
    2. Socket socket = new Socket("192.168.1.32", 1989);
    3. // 判断客户端和服务器是否连接成功
    4. socket.isConnected());
  1. // 步骤2:客户端 & 服务器 通信
  2. // 通信包括:客户端 接收服务器的数据 & 发送数据 到 服务器
  3. <-- 操作1:接收服务器的数据 -->
  4. // 步骤1:创建输入流对象InputStream
  5. InputStream is = socket.getInputStream()
  6. // 步骤2:创建输入流读取器对象 并传入输入流对象
  7. // 该对象作用:获取服务器返回的数据
  8. InputStreamReader isr = new InputStreamReader(is);
  9. BufferedReader br = new BufferedReader(isr);
  10. // 步骤3:通过输入流读取器对象 接收服务器发送过来的数据
  11. br.readLine();
  12. <-- 操作2:发送数据 服务器 -->
  13. // 步骤1:从Socket 获得输出流对象OutputStream
  14. // 该对象作用:发送数据
  15. OutputStream outputStream = socket.getOutputStream();
  16. // 步骤2:写入需要发送的数据到输出流对象中
  17. outputStream.write(("Carson_Ho"+"\n").getBytes("utf-8"));
  18. // 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞
  19. // 步骤3:发送数据到服务端
  20. outputStream.flush();
  21. // 步骤3:断开客户端 & 服务器 连接
  22. os.close();
  23. // 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream
  24. br.close();
  25. // 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader
  26. socket.close();
  27. // 最终关闭整个Socket连接
  28. 1
  29. 2
  30. 3
  31. 4
  32. 5
  33. 6
  34. 7
  35. 8
  36. 9
  37. 10
  38. 11
  39. 12
  40. 13
  41. 14
  42. 15
  43. 16
  44. 17
  45. 18
  46. 19
  47. 20
  48. 21
  49. 22
  50. 23
  51. 24
  52. 25
  53. 26
  54. 27
  55. 28
  56. 29
  57. 30
  58. 31
  59. 32
  60. 33
  61. 34
  62. 35
  63. 36
  64. 37
  65. 38
  66. 39
  67. 40
  68. 41
  69. 42
  70. 43
  71. 44
  72. 45
  73. 46
  74. 47
  75. 48
  76. 49
  77. 50
  78. 51
  79. 1
  80. 2
  81. 3
  82. 4
  83. 5
  84. 6
  85. 7
  86. 8
  87. 9
  88. 10
  89. 11
  90. 12
  91. 13
  92. 14
  93. 15
  94. 16
  95. 17
  96. 18
  97. 19
  98. 20
  99. 21
  100. 22
  101. 23
  102. 24
  103. 25
  104. 26
  105. 27
  106. 28
  107. 29
  108. 30
  109. 31
  110. 32
  111. 33
  112. 34
  113. 35
  114. 36
  115. 37
  116. 38
  117. 39
  118. 40
  119. 41
  120. 42
  121. 43
  122. 44
  123. 45
  124. 46
  125. 47
  126. 48
  127. 49
  128. 50
  129. 51

6. 具体实例

  • 实例 Demo 代码包括:客户端 & 服务器
  • 本文着重讲解客户端,服务器仅采用最简单的写法进行展示

6.1 客户端 实现

步骤1:加入网络权限

  1. <uses-permission android:name="android.permission.INTERNET" />
  2. 1
  3. 1

步骤2:主布局界面设置

包括创建Socket连接、客户端 & 服务器通信的按钮

  1. <Button
  2. android:id="@+id/connect"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:text="connect" />
  6. <Button
  7. android:id="@+id/disconnect"
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content"
  10. android:text="disconnect" />
  11. <TextView
  12. android:id="@+id/receive_message"
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content" />
  15. <Button
  16. android:id="@+id/Receive"
  17. android:layout_width="match_parent"
  18. android:layout_height="wrap_content"
  19. android:text="Receive from message" />
  20. <EditText
  21. android:id="@+id/edit"
  22. android:layout_width="match_parent"
  23. android:layout_height="wrap_content" />
  24. <Button
  25. android:id="@+id/send"
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"
  28. android:text="send"/>
  29. 1
  30. 2
  31. 3
  32. 4
  33. 5
  34. 6
  35. 7
  36. 8
  37. 9
  38. 10
  39. 11
  40. 12
  41. 13
  42. 14
  43. 15
  44. 16
  45. 17
  46. 18
  47. 19
  48. 20
  49. 21
  50. 22
  51. 23
  52. 24
  53. 25
  54. 26
  55. 27
  56. 28
  57. 29
  58. 30
  59. 31
  60. 32
  61. 33
  62. 34
  63. 1
  64. 2
  65. 3
  66. 4
  67. 5
  68. 6
  69. 7
  70. 8
  71. 9
  72. 10
  73. 11
  74. 12
  75. 13
  76. 14
  77. 15
  78. 16
  79. 17
  80. 18
  81. 19
  82. 20
  83. 21
  84. 22
  85. 23
  86. 24
  87. 25
  88. 26
  89. 27
  90. 28
  91. 29
  92. 30
  93. 31
  94. 32
  95. 33
  96. 34

步骤3:创建Socket连接、客户端 & 服务器通信

具体请看注释

MainActivity.Java

  1. package scut.carson_ho.socket_carson;
  2. import android.os.Bundle;
  3. import android.os.Handler;
  4. import android.os.Message;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.view.View;
  7. import android.widget.Button;
  8. import android.widget.EditText;
  9. import android.widget.TextView;
  10. import java.io.BufferedReader;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.io.InputStreamReader;
  14. import java.io.OutputStream;
  15. import java.net.Socket;
  16. import java.util.concurrent.ExecutorService;
  17. import java.util.concurrent.Executors;
  18. public class MainActivity extends AppCompatActivity {
  19. /**
  20. * 主 变量
  21. */
  22. // 主线程Handler
  23. // 用于将从服务器获取的消息显示出来
  24. private Handler mMainHandler;
  25. // Socket变量
  26. private Socket socket;
  27. // 线程池
  28. // 为了方便展示,此处直接采用线程池进行线程管理,而没有一个个开线程
  29. private ExecutorService mThreadPool;
  30. /**
  31. * 接收服务器消息 变量
  32. */
  33. // 输入流对象
  34. InputStream is;
  35. // 输入流读取器对象
  36. InputStreamReader isr ;
  37. BufferedReader br ;
  38. // 接收服务器发送过来的消息
  39. String response;
  40. /**
  41. * 发送消息到服务器 变量
  42. */
  43. // 输出流对象
  44. OutputStream outputStream;
  45. /**
  46. * 按钮 变量
  47. */
  48. // 连接 断开连接 发送数据到服务器 的按钮变量
  49. private Button btnConnect, btnDisconnect, btnSend;
  50. // 显示接收服务器消息 按钮
  51. private TextView Receive,receive_message;
  52. // 输入需要发送的消息 输入框
  53. private EditText mEdit;
  54. @Override
  55. protected void onCreate(Bundle savedInstanceState) {
  56. super.onCreate(savedInstanceState);
  57. setContentView(R.layout.activity_main);
  58. /**
  59. * 初始化操作
  60. */
  61. // 初始化所有按钮
  62. btnConnect = (Button) findViewById(R.id.connect);
  63. btnDisconnect = (Button) findViewById(R.id.disconnect);
  64. btnSend = (Button) findViewById(R.id.send);
  65. mEdit = (EditText) findViewById(R.id.edit);
  66. receive_message = (TextView) findViewById(R.id.receive_message);
  67. Receive = (Button) findViewById(R.id.Receive);
  68. // 初始化线程池
  69. mThreadPool = Executors.newCachedThreadPool();
  70. // 实例化主线程,用于更新接收过来的消息
  71. mMainHandler = new Handler() {
  72. @Override
  73. public void handleMessage(Message msg) {
  74. switch (msg.what) {
  75. case 0:
  76. receive_message.setText(response);
  77. break;
  78. }
  79. }
  80. };
  81. /**
  82. * 创建客户端 & 服务器的连接
  83. */
  84. btnConnect.setOnClickListener(new View.OnClickListener() {
  85. @Override
  86. public void onClick(View v) {
  87. // 利用线程池直接开启一个线程 & 执行该线程
  88. mThreadPool.execute(new Runnable() {
  89. @Override
  90. public void run() {
  91. try {
  92. // 创建Socket对象 & 指定服务端的IP 及 端口号
  93. socket = new Socket("192.168.1.172", 8989);
  94. // 判断客户端和服务器是否连接成功
  95. System.out.println(socket.isConnected());
  96. } catch (IOException e) {
  97. e.printStackTrace();
  98. }
  99. }
  100. });
  101. }
  102. });
  103. /**
  104. * 接收 服务器消息
  105. */
  106. Receive.setOnClickListener(new View.OnClickListener() {
  107. @Override
  108. public void onClick(View v) {
  109. // 利用线程池直接开启一个线程 & 执行该线程
  110. mThreadPool.execute(new Runnable() {
  111. @Override
  112. public void run() {
  113. try {
  114. // 步骤1:创建输入流对象InputStream
  115. is = socket.getInputStream();
  116. // 步骤2:创建输入流读取器对象 并传入输入流对象
  117. // 该对象作用:获取服务器返回的数据
  118. isr = new InputStreamReader(is);
  119. br = new BufferedReader(isr);
  120. // 步骤3:通过输入流读取器对象 接收服务器发送过来的数据
  121. response = br.readLine();
  122. // 步骤4:通知主线程,将接收的消息显示到界面
  123. Message msg = Message.obtain();
  124. msg.what = 0;
  125. mMainHandler.sendMessage(msg);
  126. } catch (IOException e) {
  127. e.printStackTrace();
  128. }
  129. }
  130. });
  131. }
  132. });
  133. /**
  134. * 发送消息 给 服务器
  135. */
  136. btnSend.setOnClickListener(new View.OnClickListener() {
  137. @Override
  138. public void onClick(View v) {
  139. // 利用线程池直接开启一个线程 & 执行该线程
  140. mThreadPool.execute(new Runnable() {
  141. @Override
  142. public void run() {
  143. try {
  144. // 步骤1:从Socket 获得输出流对象OutputStream
  145. // 该对象作用:发送数据
  146. outputStream = socket.getOutputStream();
  147. // 步骤2:写入需要发送的数据到输出流对象中
  148. outputStream.write((mEdit.getText().toString()+"\n").getBytes("utf-8"));
  149. // 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞
  150. // 步骤3:发送数据到服务端
  151. outputStream.flush();
  152. } catch (IOException e) {
  153. e.printStackTrace();
  154. }
  155. }
  156. });
  157. }
  158. });
  159. /**
  160. * 断开客户端 & 服务器的连接
  161. */
  162. btnDisconnect.setOnClickListener(new View.OnClickListener() {
  163. @Override
  164. public void onClick(View v) {
  165. try {
  166. // 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream
  167. outputStream.close();
  168. // 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader
  169. br.close();
  170. // 最终关闭整个Socket连接
  171. socket.close();
  172. // 判断客户端和服务器是否已经断开连接
  173. System.out.println(socket.isConnected());
  174. } catch (IOException e) {
  175. e.printStackTrace();
  176. }
  177. }
  178. });
  179. }
  180. }
  181. 1
  182. 2
  183. 3
  184. 4
  185. 5
  186. 6
  187. 7
  188. 8
  189. 9
  190. 10
  191. 11
  192. 12
  193. 13
  194. 14
  195. 15
  196. 16
  197. 17
  198. 18
  199. 19
  200. 20
  201. 21
  202. 22
  203. 23
  204. 24
  205. 25
  206. 26
  207. 27
  208. 28
  209. 29
  210. 30
  211. 31
  212. 32
  213. 33
  214. 34
  215. 35
  216. 36
  217. 37
  218. 38
  219. 39
  220. 40
  221. 41
  222. 42
  223. 43
  224. 44
  225. 45
  226. 46
  227. 47
  228. 48
  229. 49
  230. 50
  231. 51
  232. 52
  233. 53
  234. 54
  235. 55
  236. 56
  237. 57
  238. 58
  239. 59
  240. 60
  241. 61
  242. 62
  243. 63
  244. 64
  245. 65
  246. 66
  247. 67
  248. 68
  249. 69
  250. 70
  251. 71
  252. 72
  253. 73
  254. 74
  255. 75
  256. 76
  257. 77
  258. 78
  259. 79
  260. 80
  261. 81
  262. 82
  263. 83
  264. 84
  265. 85
  266. 86
  267. 87
  268. 88
  269. 89
  270. 90
  271. 91
  272. 92
  273. 93
  274. 94
  275. 95
  276. 96
  277. 97
  278. 98
  279. 99
  280. 100
  281. 101
  282. 102
  283. 103
  284. 104
  285. 105
  286. 106
  287. 107
  288. 108
  289. 109
  290. 110
  291. 111
  292. 112
  293. 113
  294. 114
  295. 115
  296. 116
  297. 117
  298. 118
  299. 119
  300. 120
  301. 121
  302. 122
  303. 123
  304. 124
  305. 125
  306. 126
  307. 127
  308. 128
  309. 129
  310. 130
  311. 131
  312. 132
  313. 133
  314. 134
  315. 135
  316. 136
  317. 137
  318. 138
  319. 139
  320. 140
  321. 141
  322. 142
  323. 143
  324. 144
  325. 145
  326. 146
  327. 147
  328. 148
  329. 149
  330. 150
  331. 151
  332. 152
  333. 153
  334. 154
  335. 155
  336. 156
  337. 157
  338. 158
  339. 159
  340. 160
  341. 161
  342. 162
  343. 163
  344. 164
  345. 165
  346. 166
  347. 167
  348. 168
  349. 169
  350. 170
  351. 171
  352. 172
  353. 173
  354. 174
  355. 175
  356. 176
  357. 177
  358. 178
  359. 179
  360. 180
  361. 181
  362. 182
  363. 183
  364. 184
  365. 185
  366. 186
  367. 187
  368. 188
  369. 189
  370. 190
  371. 191
  372. 192
  373. 193
  374. 194
  375. 195
  376. 196
  377. 197
  378. 198
  379. 199
  380. 200
  381. 201
  382. 202
  383. 203
  384. 204
  385. 205
  386. 206
  387. 207
  388. 208
  389. 209
  390. 210
  391. 211
  392. 212
  393. 213
  394. 214
  395. 215
  396. 216
  397. 217
  398. 218
  399. 219
  400. 220
  401. 221
  402. 222
  403. 223
  404. 224
  405. 225
  406. 226
  407. 227
  408. 228
  409. 229
  410. 230
  411. 231
  412. 232
  413. 233
  414. 234
  415. 235
  416. 236
  417. 237
  418. 238
  419. 239
  420. 240
  421. 241
  422. 1
  423. 2
  424. 3
  425. 4
  426. 5
  427. 6
  428. 7
  429. 8
  430. 9
  431. 10
  432. 11
  433. 12
  434. 13
  435. 14
  436. 15
  437. 16
  438. 17
  439. 18
  440. 19
  441. 20
  442. 21
  443. 22
  444. 23
  445. 24
  446. 25
  447. 26
  448. 27
  449. 28
  450. 29
  451. 30
  452. 31
  453. 32
  454. 33
  455. 34
  456. 35
  457. 36
  458. 37
  459. 38
  460. 39
  461. 40
  462. 41
  463. 42
  464. 43
  465. 44
  466. 45
  467. 46
  468. 47
  469. 48
  470. 49
  471. 50
  472. 51
  473. 52
  474. 53
  475. 54
  476. 55
  477. 56
  478. 57
  479. 58
  480. 59
  481. 60
  482. 61
  483. 62
  484. 63
  485. 64
  486. 65
  487. 66
  488. 67
  489. 68
  490. 69
  491. 70
  492. 71
  493. 72
  494. 73
  495. 74
  496. 75
  497. 76
  498. 77
  499. 78
  500. 79
  501. 80
  502. 81
  503. 82
  504. 83
  505. 84
  506. 85
  507. 86
  508. 87
  509. 88
  510. 89
  511. 90
  512. 91
  513. 92
  514. 93
  515. 94
  516. 95
  517. 96
  518. 97
  519. 98
  520. 99
  521. 100
  522. 101
  523. 102
  524. 103
  525. 104
  526. 105
  527. 106
  528. 107
  529. 108
  530. 109
  531. 110
  532. 111
  533. 112
  534. 113
  535. 114
  536. 115
  537. 116
  538. 117
  539. 118
  540. 119
  541. 120
  542. 121
  543. 122
  544. 123
  545. 124
  546. 125
  547. 126
  548. 127
  549. 128
  550. 129
  551. 130
  552. 131
  553. 132
  554. 133
  555. 134
  556. 135
  557. 136
  558. 137
  559. 138
  560. 139
  561. 140
  562. 141
  563. 142
  564. 143
  565. 144
  566. 145
  567. 146
  568. 147
  569. 148
  570. 149
  571. 150
  572. 151
  573. 152
  574. 153
  575. 154
  576. 155
  577. 156
  578. 157
  579. 158
  580. 159
  581. 160
  582. 161
  583. 162
  584. 163
  585. 164
  586. 165
  587. 166
  588. 167
  589. 168
  590. 169
  591. 170
  592. 171
  593. 172
  594. 173
  595. 174
  596. 175
  597. 176
  598. 177
  599. 178
  600. 179
  601. 180
  602. 181
  603. 182
  604. 183
  605. 184
  606. 185
  607. 186
  608. 187
  609. 188
  610. 189
  611. 190
  612. 191
  613. 192
  614. 193
  615. 194
  616. 195
  617. 196
  618. 197
  619. 198
  620. 199
  621. 200
  622. 201
  623. 202
  624. 203
  625. 204
  626. 205
  627. 206
  628. 207
  629. 208
  630. 209
  631. 210
  632. 211
  633. 212
  634. 213
  635. 214
  636. 215
  637. 216
  638. 217
  639. 218
  640. 219
  641. 220
  642. 221
  643. 222
  644. 223
  645. 224
  646. 225
  647. 226
  648. 227
  649. 228
  650. 229
  651. 230
  652. 231
  653. 232
  654. 233
  655. 234
  656. 235
  657. 236
  658. 237
  659. 238
  660. 239
  661. 240
  662. 241

6.2 服务器 实现

  • 因本文主要讲解客户端,所以服务器仅仅是为了配合客户端展示;
  • 为了简化服务器使用,此处采用Mina框架
  1. 服务器代码请在eclipse平台运行
  2. 按照我的步骤一步步实现就可以无脑运行了

步骤1:导入Mina

请直接移步到百度网盘:下载链接(密码: q73e)

示意图

步骤2:创建服务器线程
TestHandler.java

  1. package mina;
  2. // 导入包
  3. public class TestHandler extends IoHandlerAdapter {
  4. @Override
  5. public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
  6. System.out.println("exceptionCaught: " + cause);
  7. }
  8. @Override
  9. public void messageReceived(IoSession session, Object message) throws Exception {
  10. System.out.println("recieve : " + (String) message);
  11. session.write("hello I am server");
  12. }
  13. @Override
  14. public void messageSent(IoSession session, Object message) throws Exception {
  15. }
  16. @Override
  17. public void sessionClosed(IoSession session) throws Exception {
  18. System.out.println("sessionClosed");
  19. }
  20. @Override
  21. public void sessionOpened(IoSession session) throws Exception {
  22. System.out.println("sessionOpen");
  23. }
  24. @Override
  25. public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
  26. }
  27. }
  28. 1
  29. 2
  30. 3
  31. 4
  32. 5
  33. 6
  34. 7
  35. 8
  36. 9
  37. 10
  38. 11
  39. 12
  40. 13
  41. 14
  42. 15
  43. 16
  44. 17
  45. 18
  46. 19
  47. 20
  48. 21
  49. 22
  50. 23
  51. 24
  52. 25
  53. 26
  54. 27
  55. 28
  56. 29
  57. 30
  58. 31
  59. 32
  60. 33
  61. 34
  62. 35
  63. 36
  64. 37
  65. 1
  66. 2
  67. 3
  68. 4
  69. 5
  70. 6
  71. 7
  72. 8
  73. 9
  74. 10
  75. 11
  76. 12
  77. 13
  78. 14
  79. 15
  80. 16
  81. 17
  82. 18
  83. 19
  84. 20
  85. 21
  86. 22
  87. 23
  88. 24
  89. 25
  90. 26
  91. 27
  92. 28
  93. 29
  94. 30
  95. 31
  96. 32
  97. 33
  98. 34
  99. 35
  100. 36
  101. 37

步骤3:创建服务器主代码
TestHandler.java

  1. package mina;
  2. import java.io.IOException;
  3. import java.net.InetSocketAddress;
  4. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  5. import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
  6. import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
  7. public class TestServer {
  8. public static void main(String[] args) {
  9. NioSocketAcceptor acceptor = null;
  10. try {
  11. acceptor = new NioSocketAcceptor();
  12. acceptor.setHandler(new TestHandler());
  13. acceptor.getFilterChain().addLast("mFilter", new ProtocolCodecFilter(new TextLineCodecFactory()));
  14. acceptor.setReuseAddress(true);
  15. acceptor.bind(new InetSocketAddress(8989));
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }
  21. 1
  22. 2
  23. 3
  24. 4
  25. 5
  26. 6
  27. 7
  28. 8
  29. 9
  30. 10
  31. 11
  32. 12
  33. 13
  34. 14
  35. 15
  36. 16
  37. 17
  38. 18
  39. 19
  40. 20
  41. 21
  42. 22
  43. 23
  44. 24
  45. 1
  46. 2
  47. 3
  48. 4
  49. 5
  50. 6
  51. 7
  52. 8
  53. 9
  54. 10
  55. 11
  56. 12
  57. 13
  58. 14
  59. 15
  60. 16
  61. 17
  62. 18
  63. 19
  64. 20
  65. 21
  66. 22
  67. 23
  68. 24

至此,客户端 & 服务器的代码均实现完毕。

发表评论

表情:
评论列表 (有 0 条评论,255人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Socket通信原理实践

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ

    相关 Socket通信原理实践

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ

    相关 Socket基本原理

    网络编程,一切皆Socket 一、一些总结 Http通信,应用层协议,之前看过okhttp的部分源码,主要是五层的拦截器逻辑,最终的通信方式是封装的一个使用o

    相关 Socket通信原理

    对TCP/IP、UDP、Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。那么我想问: 1.         什么是TCP/IP

    相关 Socket基本原理

                    一、Socket简介 1、套接字(socket)概念 套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。