欢迎来到顔をしての博客吖,如果文章记得不错|

园龄:粉丝:关注:

2023-01-30 17:28阅读: 50评论: 0推荐: 0

socket网络通信

整理和总结了一下大家常遇到的问题:

​ 1. 客户端socket发送消息后,为什么服务端socket没有收到?

​ 2. 使用while 循环实现连续输入,是不是就是多线程模式?

​ 3. 对多线程处理机制不是很明白,希望详细讲解?

​ 4. 希望详细讲解ServerSocketChannel和SocketChannel与ServerSoket和Socket的区别?

​ 5. 希望有详细的例子,可以直接拷贝下来运行?

一:socket通信基本原理。

首先socket 通信是基于TCP/IP 网络层上的一种传送方式,我们通常把TCP和UDP称为传输层。

0

如上图,在七个层级关系中,我们将的socket属于传输层,其中UDP是一种面向无连接的传输层协议。UDP不关心对端是否真正收到了传送过去的数据。如果需要检查对端是否收到分组数据包,或者对端是否连接到网络,则需要在应用程序中实现。UDP常用在分组数据较少或多播、广播通信以及视频通信等多媒体领域。在这里我们不进行详细讨论,这里主要讲解的是基于TCP/IP协议下的socket通信。

socket是基于应用服务与TCP/IP通信之间的一个抽象,他将TCP/IP协议里面复杂的通信逻辑进行分装,对用户来说,只要通过一组简单的API就可以实现网络的连接。借用网络上一组socket通信图给大家进行详细讲解:

0

首先,服务端初始化ServerSocket,然后对指定的端口进行绑定,接着对端口及进行监听,通过调用accept方法阻塞,此时,如果客户端有一个socket连接到服务端,那么服务端通过监听和accept方法可以与客户端进行连接。

二:socket通信基本示例:

在对socket通信基本原理明白后,那我们就写一个最简单的示例,展示童鞋们常遇到的第一个问题:客户端发送消息后,服务端无法收到消息。

import java.io.BufferedWriter; import java.io.OutputStreamWriter; import java.net.Socket; public class ClientSocketTest { public static void main(String[] args) { BufferedWriter bw = null; try { Socket so = new Socket("127.0.0.1", 8888); bw = new BufferedWriter(new OutputStreamWriter(so.getOutputStream())); String str = "你好,这是我的第一个socket"; bw.write(str); } catch (Exception e) { e.printStackTrace(); } finally { try { if (bw != null) bw.close(); } catch (Exception e) { e.printStackTrace(); } } } }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class ServerSocketTest { public static void main(String[] args) { BufferedReader br = null; try { // 初始化服务端socket并且绑定8888端口 ServerSocket ss = new ServerSocket(8888); // 等待客户端的连接 Socket so = ss.accept(); // 获取输入流 br = new BufferedReader(new InputStreamReader(so.getInputStream())); // 读取一行数据 String str = br.readLine(); // 输出打印 System.out.println("连接到server\t" + str); } catch (Exception e) { e.printStackTrace(); } finally { try { if (br != null) br.close(); } catch (Exception e) { e.printStackTrace(); } } } }

0

0

然后好多童鞋,就拷贝这个java.net.SocketException: Connection reset上网查异常,查询解决方案,搞了半天都不知道怎么回事。解决这个问题我们首先要明白,socket通信是阻塞的,他会在以下几个地方进行阻塞。第一个是accept方法,调用这个方法后,服务端一直阻塞在哪里,直到有客户端连接进来。第二个是read方法,调用read方法也会进行阻塞。通过上面的示例我们可以发现,该问题发生在read方法中。有朋友说是Client没有发送成功,其实不是的,我们可以通debug跟踪一下,发现客户端发送了,并且没有问题。而是发生在服务端中,当服务端调用read方法后,他一直阻塞在哪里,因为客户端没有给他一个标识,告诉是否消息发送完成,所以服务端还在一直等待接受客户端的数据,结果客户端此时已经关闭了,就是在服务端报错:java.net.SocketException: Connection reset

那么理解上面的原理后,我们就能明白,客户端发送完消息后,需要给服务端一个标识,告诉服务端,我已经发送完成了,服务端就可以将接受的消息打印出来。

​ 通常大家会用以下方法进行进行结束:

socket.close() 或者调用socket.shutdownOutput();方法。调用这俩个方法,都会结束客户端socket。但是有本质的区别。socket.close() 将socket关闭连接,那边如果有服务端给客户端反馈信息,此时客户端是收不到的。而socket.shutdownOutput()是将输出流关闭,此时,如果服务端有信息返回,则客户端是可以正常接受的。现在我们将上面的客户端示例修改一下啊,增加一个标识告诉流已经输出完毕:

本文作者:顔をして

本文链接:https://www.cnblogs.com/ynxiyan/p/17076745.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   顔をして  阅读(50)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 I Really Want to Stay at Your House Samuel Kim,Lorien
  2. 2 将月亮藏进躯体 豆芽鱼(庄东茹)
  3. 3 辞九门回忆 解忧草,冰幽
  4. 4 I'M Not Girl 伊晗
辞九门回忆 - 解忧草,冰幽
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 虫二颠

作曲 : 唯子/妖狐公子

一曲定重楼

一眼半生筹

看的全都是那诡谲云涌

入得此门不回首

无需宣之于口

我对案再拜那风雨瓢泼的残陋

再聚首

戏子多秋

可怜一处情深旧

满座衣冠皆老朽

黄泉故事无止休

戏无骨难左右

换过一折又重头

只道最是人间不能留

误闯天家

劝余放下手中砂

张口欲唱声却哑

粉面披衣叫个假

怜余来安座下

不敢沾染佛前茶

只作凡人赴雪月风花

绕过胭脂楼

打散结发扣

唱的全都是那情深不寿

入得此门不回首

无需宣之于口

我对镜遮掩那风雨瓢泼的残陋

碑已旧

戏子多秋

可怜一处情深旧

满座衣冠皆老朽

黄泉故事无止休

戏无骨难左右

换过一折又重头

只道最是人间不能留

误闯天家

劝余放下手中砂

送那人御街打马

才子佳人断佳话

怜余来苦咽下

求不得佛前茶

只留三寸土种二月花