当前位置:首页 > 数据库 > 正文

java socket编程实例 JAVA编程实例

java socket编程实例 JAVA编程实例

大家好,今天小编来为大家解答java这个问题,JAVA编程实例很多人还不知道,现在让我们一起来看看吧!遇到java.net.SocketTimeoutException...

大家好,今天小编来为大家解答java这个问题,JAVA编程实例很多人还不知道,现在让我们一起来看看吧!

遇到java.net.SocketTimeoutException:Readtimedout怎么办

连接超时,确保网络通畅后重连,若还连不上是他们服务器的问题这样可以么?

java socket客户端怎样确认服务器端是否收到数据

在服务端接收完数据之后返回一个接收完毕的通知给客户端,告诉客户端我已经把数据接收完了。

如何使用Socket在客户端实现长连接

长连接貌似是一个很高深莫测的知识,但是只要你做直播、IM、游戏、弹幕里面的任何一种,或者是你的app想要实时的接收某些消息,你就会要接触到长连接技术。本文主要教你如何在客户端如何使用Socket实现长连接。

Socket背景知识

要做长连接的话,是不能用http协议来做的,因为http协议已经是应用层协议了,并且http协议是无状态的,而我们要做长连接,肯定是需要在应用层封装自己的业务,所以就需要基于TCP协议来做,而基于TCP协议的话,就要用到Socket了。

Socket是java针对tcp层通信封装的一套网络方案

TCP协议我们知道,是基于ip(或者域名)和端口对指定机器进行的点对点访问,他的连接成功有两个条件,就是对方ip可以到达和端口是开放的

Socket能帮完成TCP三次握手,而应用层的头部信息需要自己去解析,也就是说,自己要制定好协议,并且要去解析byte

http也有长连接。在http1.0的时候,使用的是短连接,也就是说,每次请求一次数据,都要重新建立连接。但是从http1.1之后,我们看到头部会有一个

Connection:keep-alive

这个表示tcp连接建立之后不会马上销毁,而是保存一段时间,在这段时间内如果需要请求改网站的其他数据,都是使用这个连接来完成传输的。

Socket使用方式

Socket看上去不是很好用,因为他是基于java.io来实现的,你要直接跟InputStream和OutputStream打交道,也就是直接跟byte[]打交道,所以用起来并不是这么友好。

下面通过一个简单的例子,往一台服务器发\01\00\00\00\00这一串字节,服务器也返回相同的字节流,上代码:

@Test

publicvoidtestSocket()throwsException{

logger.debug("start");

Socketsocket=newSocket();

socket.connect(address);

byte[]output=newbyte[]{(byte)1,(byte)0,(byte)0,(byte)0,(byte)0};

socket.getOutputStream().write(output);

byte[]input=newbyte[64];

intreadByte=socket.getInputStream().read(input);

logger.debug("readByte"+readByte);

for(inti=0;i<readByte;i++){

logger.debug("read["+i+"]:"+input[i]);

}

socket.close();

}

输出:

11:40:40.326[main]DEBUGcom.roy.test.SocketTest-start

11:40:40.345[main]DEBUGcom.roy.test.SocketTest-readByte5

11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read1

11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0

11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0

11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0

11:40:40.345[main]DEBUGcom.roy.test.SocketTest-read0

看出来写起来还是比较麻烦的,主要就是InputStream,OutputStream和byte[]使用起来太不方便了。

SocketChannelblocking

Socket为了优化自己的封装和并发性能,推出了nio包下面的SocketChannel,这个相比于Socket的好处就是并发性能的提高和封装的优化了。

SocketChannel有两种方式——阻塞和非阻塞的,阻塞的用法和Socket差不多,都是在read和write的时候会阻塞线程,下面用一段代码来实现相同的功能。

@Test

publicvoidtestSocketChannelBlock()throwsException{

finalSocketChannelchannel=SocketChannel.open(address);

ByteBufferoutput=ByteBuffer.allocate(5);

output.put((byte)1);

output.putInt(0);

output.flip();

channel.write(output);

logger.debug("writecomplete,startread");

ByteBufferinput=ByteBuffer.allocate(5);

intreadByte=channel.read(input);

logger.debug("readByte"+readByte);

input.flip();

if(readByte==-1){

logger.debug("readByte==-1,return!");

return;

}

for(inti=0;i<readByte;i++){

logger.debug("read["+i+"]:"+input.get());

}

}

log输出:

23:24:34.684[main]DEBUGcom.dz.test.SocketTest-writecomplete,startread

23:24:34.901[main]DEBUGcom.dz.test.SocketTest-readByte5

23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[0]:1

23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[1]:0

23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[2]:0

23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[3]:0

23:24:34.901[main]DEBUGcom.dz.test.SocketTest-read[4]:0

从上面的。封装优化主要体现在ByteBuffer,IntBuffer这一系列类的封装——因为是网络相关的,所以这里用到的主要是ByteBuffer。

ByteBuffer和byte[]最大的区别,就是ByteBuffer可以很方便的读取int,long等数据类型,他提供了getInt(),getInt(intoffset)这样的方法,这种方法主要用在识别头部数据部分,因为头部数据一般都是由多种数据类型组成,比方说表示数据格式的contentType:String,表示长度的length:int等等,这些就是getInt()这样的方法主要的应用场景,而byte[]如果要取int,String相对来说就要复杂一些了,这是java.nio相比于java.io优势的一点。

这里需要说明一个比较坑的点,就是ByteBuffer.flip()这个方法,这个方法的作用主要是重置索引,在write()之前和read()之后调用,否则会因为索引不对,导致你的数据写不进去,读不出来。

ByteBuffer是一个功能强大的类,因为本文主要是讲Socket和SocketChannel,所以在这里就不做过多描述。具体ByteBuffer的详细介绍,可以参考:JavaNIO系列教程(三)Buffer

而nio相比于io最大的优势还是在于并发性能,因为nio里面的n代表的就是non-blocking的意思,上面那个读取数据的代码也相对老旧,一般我们如果要用SocketChannel,都是用non-blocking的方式来实现的,而如果要用non-blocking模式,首先要介绍的就是Selector。

Selector

我们知道,传统io是阻塞的,也就是说,一个线程只能处理一个io流,也就是一个Socket。有了Selector之后,一个线程就能处理多个SocketChannel。

Selector的原

自学java感到学到自己的瓶颈期了,各种框架乱七八糟,感觉好乱。该怎么办

下面是我的视频里大概要介绍的内容:

如何看待框架

知其然,知其所以然。不仅要学会使用框架,还需要学会框架的原理。最好的方法是自己动手模仿着做一下。一动手你就开始从框架设计者的角度考虑问题了。你思考问题的角度和高度就和以前不一样了。

如何突破瓶颈,更上一层楼

学习算法和设计模式。思考框架要解决的本质问题。评价这种方法的优缺点。如果是你,你有什么改进意见。可以参考我的动画视频,讲解了很多分布式系统的设计原理。

推荐几本好书,值得精读很多遍的书

大多数人的悟性是差不多的。多读好书,可以从前辈大牛,甚至是世界级顶级专家那里得到指导和启发。

下面这本书是MIT的本科教材,网上有作者的公开课。可以找了看看。

下面这本书是关于分布式系统应用设计中遇到的问题和通常的解决思路。比如hadoop,kafka,flink,zookeeper,raft他们都是用来解决什么问题的。

本人,@小马过河Vizit,专注于分布式系统原理和实践分享。希望利用动画生动而又准确地演示抽象的原理。

关于我的名字。小马过河Vizit,意为凡事像小马过河一样,需要自己亲自尝试、探索才能获得乐趣和新知。Vizit是指Visualizeit的缩写。一图胜千言,希望可以利用动画来可视化抽象的原理。

欢迎关注,点赞!谢谢支持。

socket建立连接的步骤

javasocket建立连接的过程如下:

1、首先调用Socket类的构造函数,以服务器的指定的IP地址或指定的主机名和指定的端口号为参数,创建一个Socket流,在创建Socket流的过程中包含了向服务器请求建立通讯连接的过程实现。

2、建立了客户端通讯Socket后。就可以使用Socket的方法getInputStream()和getOutputStream()来创建输入/输出流。这样,使用Socket类后,网络输入输出也转化为使用流对象的过程。

3、使用输入输出流对象的相应方法读写字节流数据,因为流连接着通讯所用的Socket,Socket又是和服务器端建立连接的一个端点,因此数据将通过连接从服务器得到或发向服务器。这时我们就可以对字节流数据按客户端和服务器之间的协议进行处理,完成双方的通讯任务。

4、待通讯任务完毕后,我们用流对象的close()方法来关闭用于网络通讯的输入输出流,在用Socket对象的close()方法来关闭Socket。

socket双向连接的建立过程

javasocket建立连接的过程如下:socket

1、首先调用Socket类的构造函数,以服务器的指定的IP地址或指定的主机名和指定的端口号为参数,创建一个Socket流,在创建Socket流的过程中包含了向服务器请求建立通讯连接的过程实现。

2、建立了客户端通讯Socket后。就可以使用Socket的方法getInputStream()和getOutputStream()来创建输入/输出流。这样,使用Socket类后,网络输入输出也转化为使用流对象的过程。

3、使用输入输出流对象的相应方法读写字节流数据,因为流连接着通讯所用的Socket,Socket又是和服务器端建立连接的一个端点,因此数据将通过连接从服务器得到或发向服务器。这时我们就可以对字节流数据按客户端和服务器之间的协议进行处理,完成双方的通讯任务。

4、待通讯任务完毕后,我们用流对象的close()方法来关闭用于网络通讯的输入输出流,在用Socket对象的close()方法来关闭Socket。

OK,本文到此结束,希望对大家有所帮助。

最新文章