说明:
主要记录android socket使用方法以及netty的实现,参考自:
Java NIO,Netty笔记
1.四种IO模型
同步阻塞IO(Blocking IO):
用户进程需要内核IO操作彻底完成后,才返回到用户空间,执行用户操作;如:java中默认创建的socket;
同步非阻塞IO (Non-blocking IO):
在内核缓冲区无数据的情况下,系统调用会立即返回,返回一个调用失败的信息;在内核缓冲区有数据时,是阻塞的,直到数据从内核复制到用户缓冲区;复制完成后,系统返回调用成功,应用进程开始处理用户空间缓存的数据;
缺点:需要不断进行IO查询
IO多路复用(如Java NIO):
也属于同步IO;内核会查询所有select的可查询socket列表,当有socket数据准备好后,select就返回;用户线程获得了目标连接后,发起系统调用,用户线程阻塞,内核复制数据到用户缓冲区,返回结果;用户线程解除block状态,开始数据处理;
异步IO:
用户系统调用后,通知内核启动某个IO操作,用户线程返回;内核在整个IO操作完成后,通知用户进程,用户开始数据处理;
缺点:需要进行事件的注册、传递,需要操作系统进行大量的工作;windows系统通过IOCP实现了真正的异步IO,但目前windows很少作为百万级高并发服务器使用;linux在2.6版本才引入异步IO,目前并不完善;
2.常用socket实现:
client的实现:
fun connect(){
realSocket = Socket(host, port)
realSocket?.let {
try {
val bous = BufferedOutputStream(it.getOutputStream())
val bins = BufferedInputStream(it.getInputStream())
val text = "hello,this is a client."
Log.i(TAG, "client:send message: $text")
bous.write(text.toByteArray(Charsets.UTF_8))
bous.flush()
val buffer = ByteArray(512)
val count = bins.read(buffer)
if(count == -1){
Log.i(TAG, "client:read count = -1")
}
val msg = String(buffer, 0, count)
Log.i(TAG, "client:receive message: $msg")
bins.close()
bous.close()
} catch (e: Exception){
e.printStackTrace()
Log.e(TAG, "client error:$e")
} finally {
try {
it.close()
} catch (e: Exception) {
}
}
}
}
server的实现:
server = ServerSocket(SERVER_PORT)