2、看!源码之SocketImpl源码分析

2、SocketImpl源码分析

从上一章的讲解可以看出ServerSocket就是针对SocketImpl的一个外观类,所以这章重点讲述java对SocketImpl的实现,会涉及C、C++代码所以需要阅读者有相应的基础,当然笔者也会使用最简单的语言进行描述,C大佬可跳过描述。

abstract class SocketImpl implements SocketOptions

SocketImpl实现了SocketOptions接口,而从名字就可以看出这个接口就是对Socket进行配置的,下方就是配置项也是在接口中声明的final属性。

选项 类型 意义
SO_BROADCAST BOOL 允许套接口传送广播信息。
SO_DEBUG BOOL 记录调试信息。
SO_DONTLINER BOOL 不要因为数据未发送就阻塞关闭操作。设置本选项相当于将SO_LINGER的l_onoff元素置为零。
SO_DONTROUTE BOOL 禁止选径;直接传送。
SO_KEEPALⅣE BOOL 发送“保持活动”包。
SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。
SO_OOBINLINE BOOL 在常规数据流中接收带外数据。
SO_RCVBUF int 为接收确定缓冲区大小。
SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑(参见bind())。
SO_SNDBUF int 指定发送缓冲区大小。
TCP_NODELAY BOOL 禁止发送合并的Nagle算法。
SO_TIMEOUT int 服务器连接超时时间。

SocketOptions接口除了声明了一些常量以外还有两个方法getOption、setOption,两个方法都是获取当前socket的配置值得包括上一章介绍的获取和设置缓冲区大小也是设置SocketOptions里的SO_RCVBUF属性,毕竟这里仅仅是一些声明并没有具体可说唯一值得需要关注的就是上方的那张表格。

上方代码可以看出SocketImpl是一个抽象类,里面基本是属性的声明和抽象方法的声明具体请看下表。

属性名 类型 简单描述
socket Socket 这个属性在ServerSocket中并没有使用,暂且忽略
serverSocket ServerSocket 在ServerSocket的讲解中就可以看出传入是当前对象this
fd FileDescriptor Socket的文件描述符,下方重点介绍
address InetAddress 启动服务时监听的端口地址信息
localport int 监听的端口
port int 连接的端口号,如果是客户端则是客户端端口,如果是服务accept获取的socket则是远程请求连接的端口

fd属性: 这个属性比较重要,在windows api中的socket函数的返回值就是他官方描述:socket returns a descriptor referencing the new socket。他将返回一个嵌套字描述符。而在linux下的socket方法也是返回的描述符。下面将详细对比两者描述符从而更清楚的理解他。

在讲解之前需要先学习FileDescriptor这个类。下面将是他属性列表。

属性名 类型 简单描述
fd int 描述符

看到上方列表读者可能会疑惑为什么我看到的是四个属性而我这里只列举了一个,emmm...那是因为在Socket源码解读篇并没有使用到,相信看完本讲读后读者会自己看懂那些个属性和方法的用处,这里暂不多说。
fd属性:可以在表中看出他是int类型的,而在SocketImpl中的fd属性的时候有说winapi和linux的区别下面将列举出两者源码(这里只讲windows、linux下的场景对比以后也会如此)。

windows在windows中socket方法返回的是SOCKET 一个宏定义,那么他是什么?

typedef u_int  SOCKET;

可以从上方代码看出他是u_int类型的别名(ps:u_int 则是unsigned int 代表无符号int,有符号无符号如果读者不清楚需要自己去补充这方面知识,因为就光这个就能再写一篇文章),int?一个文件描述符为什么是int呢?因为在windows编程下主要使用的是句柄而句柄就是一串int数字这个数字标识这一个内存中的类(这里可以理解在系统中是键值对而这个int则是key,而他获取的对象则就是我们使用accept或bind所需要的),暂时可以这么理解因为即使是内存也是键值对的map这里暂时不解释指针因为那玩意一说有可能是一章,所以各位读者暂时将这个int当做一个key值而调用其他socket方法都是需要这个key值的没有这个key是操作不了的。

linux在linux中socket方法比windows要直接,他直接返回的是int类型

int __sys_socket(int family, int type, int protocol)

可能你会觉得为什么在linux中我调用的试socket怎么我给的是__sys_socket是不是我出错了,并不是的笔者这里暂时挖个坑后续再说socket调用的时候自会填坑。

从上面windows和linux代码可以看出两者都是int那么久简单了在java中自然也就是int,可能有人会疑问为啥在windows是无符号在linux是有符号的,其实在linux下也是无符号的只是并没有进行标注,由下方linux源代码可看出。

static int sock_map_fd(struct socket *sock, int flags)
{
    struct file *newfile;
    //从此处获取未使用的fd最终调用的是__alloc_fd方法
    int fd = get_unused_fd_flags(flags);
    //如果返回值为false 则释放当前socket说明分配失败
    if (unlikely(fd < 0)) {
        sock_release(sock);
        return fd;
    }
    //创建新的fd,在linux下任何文件都可以当做file所以也包括socket所以这里叫做file也不为过。
    newfile = sock_alloc_file(sock, flags, NULL);
    if (likely(!IS_ERR(newfile))) {
        //如果创建成功则插入到当前进程的属性中并且计数加一
        // 在linux下所有模块都是动态加载的当计数到0的时候则会卸载模块后续或详细讲解
        fd_install(fd, newfile);
        return fd;
    }

    put_unused_fd(fd);
    return PTR_ERR(newfile);
}
int __alloc_fd(struct files_struct *files,
           unsigned start, unsigned end, unsigned flags)
{
    unsigned int fd;
}

上面都是针对linux和windows的讲解那么在java中是怎么描述的呢?

jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
int fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);

上面的代码是从SocketImpl中的bind方法的jni实现中的,可以看出他先获取了FileDescriptor对象也就是SocketImpl的fd,然后再根据FileDescriptor获取到他的fd我们最终使用的文件描述符,之前大篇幅说了fd是int的所以这里即int。 由于内容过多所以本章到此结束,下一章将会讲解SocketImpl的实现,因为一开始据说明了当前类是抽象类他自然存有实现。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容

  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,743评论 0 10
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,378评论 0 4
  • 本文摘抄自linux基础编程 IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作。那么我们对与外部设...
    VD2012阅读 1,021评论 0 2
  • 常用操作以及概念 求助 –help 指令的基本用法与选项介绍。 man man 是 manual 的缩写,将指令的...
    Fellers阅读 432评论 0 3
  • (一) 书法练习,看似简...
    SpringTang阅读 7,073评论 1 0