当前位置:首页 > CN2资讯 > 正文内容

linux java 面板 java linux api

2天前CN2资讯


最近重温网络的时候,突然发现,底层就那么些接口,java肯定也是封装了底层接口,看过我前面Nio相关的小伙伴肯定知道对这些类有点影响(Buffer,Channel,Selector,SelectionKey),可是跟底层对应不起来啊,这一篇就透过源码看一下,大概能帮助你更好的了解这几个类,及底层的实现。偏重个人兴趣向整理,如有不适,欢迎吐槽

Linux网络编程

查阅资料的时候,发现wiki百科讲的已经十分好了,相当完美的描述了Socket相关Api介绍及demo演示,由于,大学学的c语言都快还给老师了,写个demo已然不太现实,这里就臭不要脸的套用wiki百科的demo,c语言讲解部分,如果有错误欢迎指出~~。

下面是精简版本的linux网络编程,详细版可以参考链接。

LinuxAPI

socket()

  • socket() 创建一个新的确定类型的套接字,返回套接字。
  • api: int socket(int domain, int type, int protocol);
  • 参数:
  • domain: 为创建的套接字指定协议集 eg. IPV4
  • type: socket类型 eg. 流,数据报文
  • protocol: 实际传输协议 eg. TCP,UDP

bind()

  • bind() 为一个套接字分配地址。当使用socket()创建套接字后,只赋予其所使用的协议,并未分配地址。在接受其它主机的连接前,必须先调用bind()为套接字分配一个地址。
  • api: int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
  • 参数:
  • sockfd:套接字描述符,上面返回的套接字
  • my_addr: 指向sockaddr结构(用于表示所分配地址)的指针
  • addrlen: 用socklen_t字段指定了sockaddr结构的长度

listen()

  • listen() 当socket和一个地址绑定之后,listen()函数会开始监听可能的连接请求。然而,这只能在有可靠数据流保证的时候使用,例如:数据类型(SOCK_STREAM, SOCK_SEQPACKET)。
  • api:int listen(int sockfd, int backlog);
  • 参数:
  • sockfd: 套接字描述符,上面返回的套接字
  • backlog: 完成三次握手、等待accept的全连接的队列的最大长度上限。

accept()

  • accept()当应用程序监听来自其他主机的面对数据流的连接时,通过事件(比如Unix select()系统调用)通知它。必须用 accept()函数初始化连接。 Accept() 为每个连接创立新的套接字并从监听队列中移除这个连接。它使用如下参数:
  • api:int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
  • 参数:
  • sockfd:监听的套接字描述符
  • cliaddr: 指向sockaddr 结构体的指针,客户机地址信息。
  • addrlen:指向 socklen_t的指针,确定客户机地址结构体的大小 。

connect()

  • connect() 系统调用为一个套接字设置连接,参数有文件描述符和主机地址。链接到指定地址
  • api:int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
  • 参数:
  • sockfd:监听的套接字描述符
  • serv_addr: 指向sockaddr 结构体的指针,服务器地址信息。
  • addrlen:指向 socklen_t的指针,确定服务器地址结构体的大小 。

select()

  • select():在一段指定的时间内,监听用户感兴趣的文件描述符上可读、可写和异常等事件
  • api:int select (int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);
  • 参数:
  • nfds:没有用,仅仅为与伯克利Socket兼容而提供。
  • readfds:指定一个Socket数组,select检查该数组中的所有Socket。如果成功返回,则readfds中存放的是符合‘可读性’条件的数组成员(如缓冲区中有可读的数据)。
  • writefds:指定一个Socket数组,select检查该数组中的所有Socket。如果成功返回,则writefds中存放的是符合‘可写性’条件的数组成员(包括连接成功)。
  • exceptfds:指定一个Socket数组,select检查该数组中的所有Socket。如果成功返回,则cxceptfds中存放的是符合‘有异常’条件的数组成员(包括连接接失败)。
  • timeout:指定select执行的最长时间,如果在timeout限定的时间内,readfds、writefds、exceptfds中指定的Socket没有一个符合要求,就返回0。

poll()

  • poll()用于检查套接字的状态。 套接字可以被测试,看是否可以写入、读取或是有错误。
  • api:int poll(struct pollfd * fds , nfds_t nfds , int timeout );
  • 参数:
  • fds是pollfd结构体指针
  • nfdsnfds是描述符个数,结构体pollfd数组元素的个数
  • timeout:参数设置为-1时,表示永远阻塞等待。0表示立即返回,不阻塞。大于0时,表示等待指定数目的毫秒数。

fcntl()

  • fcntl()打开文件描述符,具体操作由cmd决定
  • api:int fcntl(int fd , int cmd , ... /* arg */ );
  • 参数
  • fd:文件描述符
  • cmd:操作指令

epoll_create()

  • epoll_create()在内核中创建epoll实例并返回一个epoll文件描述符。
  • api:int epoll_create(int size);
  • 参数:
  • size:而现在 size 已经没有这种语义了,但是调用者调用时 size 依然必须大于 0,以保证后向兼容性。

epoll_ctl()

  • epoll_ctl()向 epfd 对应的内核epoll 实例添加、修改或删除对 fd 上事件 event 的监听。
  • api:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  • 参数
  • epfdepoll结构体
  • opcud对应的事件枚举
  • fd文件描述符
  • events水平触发or边缘触发

epoll_wait()

  • epoll_wait()等待其管理的连接上的 IO 事件
  • api:int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
  • 参数
  • epfdepoll结构体
  • eventsepoll_event结构体指针
  • maxevents最多返回多少事件
  • timeout当 timeout 为 0 时,epoll_wait 永远会立即返回。而 timeout 为 -1 时,epoll_wait 会一直阻塞直到任一已注册的事件变为就绪。当 timeout 为一正整数时,epoll 会阻塞直到计时 timeout 毫秒终了或已注册的事件变为就绪。

send()和recv(),或者write()和read(),或者recvfrom()和sendto()等

  • 用于往/从远程套接字发送和接受数据

相关api大致如上,如有更精细的可以自行搜索。

demo

BIO

/* Server code in C */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(void) { struct sockaddr_in stSockAddr; int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if(-1 == SocketFD) { perror("can not create socket"); exit(EXIT_FAILURE); } memset(&stSockAddr, 0, sizeof(struct sockaddr_in)); stSockAddr.sin_family = AF_INET; stSockAddr.sin_port = htons(1100); stSockAddr.sin_addr.s_addr = INADDR_ANY; if(-1 == bind(SocketFD,(const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in))) { perror("error bind failed"); close(SocketFD); exit(EXIT_FAILURE); } if(-1 == listen(SocketFD, 10)) { perror("error listen failed"); close(SocketFD); exit(EXIT_FAILURE); } for(;;) { int ConnectFD = accept(SocketFD, NULL, NULL); if(0 > ConnectFD) { perror("error accept failed"); close(SocketFD); exit(EXIT_FAILURE); } /* perform read write operations ... */ shutdown(ConnectFD, SHUT_RDWR); close(ConnectFD); } close(SocketFD); return 0; }/* Client code in C */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(void) { struct sockaddr_in stSockAddr; int Res; int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (-1 == SocketFD) { perror("cannot create socket"); exit(EXIT_FAILURE); } memset(&stSockAddr, 0, sizeof(struct sockaddr_in)); stSockAddr.sin_family = AF_INET; stSockAddr.sin_port = htons(1100); Res = inet_pton(AF_INET, "192.168.1.3", &stSockAddr.sin_addr); if (0 > Res) { perror("error: first parameter is not a valid address family"); close(SocketFD); exit(EXIT_FAILURE); } else if (0 == Res) { perror("char string (second parameter does not contain valid ipaddress"); close(SocketFD); exit(EXIT_FAILURE); } if (-1 == connect(SocketFD, (const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in))) { perror("connect failed"); close(SocketFD); exit(EXIT_FAILURE); } /* perform read write operations ... */ shutdown(SocketFD, SHUT_RDWR); close(SocketFD); return 0; }

NIO

#include<stdio.h> #include<arpa/inet.h> #include<sys/epoll.h> #include<unistd.h> #include<ctype.h> #define MAXLEN 1024 #define SERV_PORT 8000 #define MAX_OPEN_FD 1024 int main(int argc,char *argv[]) { int listenfd,connfd,efd,ret; char buf[MAXLEN]; struct sockaddr_in cliaddr,servaddr; socklen_t clilen = sizeof(cliaddr); struct epoll_event tep,ep[MAX_OPEN_FD]; listenfd = socket(AF_INET,SOCK_STREAM,0); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)); listen(listenfd,20); // 创建一个epoll fd efd = epoll_create(MAX_OPEN_FD); tep.events = EPOLLIN;tep.data.fd = listenfd; // 把监听socket 先添加到efd中 ret = epoll_ctl(efd,EPOLL_CTL_ADD,listenfd,&tep); // 循环等待 for (;;) { // 返回已就绪的epoll_event,-1表示阻塞,没有就绪的epoll_event,将一直等待 size_t nready = epoll_wait(efd,ep,MAX_OPEN_FD,-1); for (int i = 0; i < nready; ++i) { // 如果是新的连接,需要把新的socket添加到efd中 if (ep[i].data.fd == listenfd ) { connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen); tep.events = EPOLLIN; tep.data.fd = connfd; ret = epoll_ctl(efd,EPOLL_CTL_ADD,connfd,&tep); } // 否则,读取数据 else { connfd = ep[i].data.fd; int bytes = read(connfd,buf,MAXLEN); // 客户端关闭连接 if (bytes == 0){ ret =epoll_ctl(efd,EPOLL_CTL_DEL,connfd,NULL); close(connfd); printf("client[%d] closed\n", i); } else { for (int j = 0; j < bytes; ++j) { buf[j] = toupper(buf[j]); } // 向客户端发送数据 write(connfd,buf,bytes); } } } } return 0; }

极度精简版本

nio已经很精简了就不多废话了

server

int main(void) { struct sockaddr_in stSockAddr; //创建套接字 int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //结构体初始化 memset(&stSockAddr, 0, sizeof(struct sockaddr_in)); stSockAddr.sin_family = AF_INET; stSockAddr.sin_port = htons(1100); stSockAddr.sin_addr.s_addr = INADDR_ANY; //绑定地址 bind(SocketFD,(const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in)); //监听请求 listen(SocketFD, 10); //接受请求 int ConnectFD = accept(SocketFD, NULL, NULL); //do something //关闭 close(ConnectFD); //关闭 close(SocketFD); return 0; }

client

int main(void) { struct sockaddr_in stSockAddr; int Res; int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); memset(&stSockAddr, 0, sizeof(struct sockaddr_in)); stSockAddr.sin_family = AF_INET; stSockAddr.sin_port = htons(1100); //IP地址转换 Res = inet_pton(AF_INET, "192.168.1.3", &stSockAddr.sin_addr); //连接地址 connect(SocketFD, (const struct sockaddr *)&stSockAddr, sizeof(struct sockaddr_in)) shutdown(SocketFD, SHUT_RDWR); close(SocketFD); return 0; }

    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/25867.html

    分享给朋友:

    “linux java 面板 java linux api” 的相关文章

    DMIT VPS评测:高性能与稳定性的完美结合

    在了解DMIT VPS之前,我想先分享一下我对这家公司的最初印象。记得第一次听到DMIT时,它的名字总是在VPS领域中流传。人们提到它时,无一不带着敬仰,增加了我对它的好奇心。自从它在2017年成立以来,DMIT便以其优秀的服务和产品迅速吸引了不少用户。我也开始关注起它背后的故事。 DMIT的崛起显...

    cping工具:高效的网络检测助手

    在网络管理的世界里,cping工具无疑是一个非常实用的助手。作为一款高效且用户友好的网络检测工具,它专注于对C类IP地址进行ICMP测试。这不仅使得网络管理员能够快速了解网络环境的状态,还能有效帮助他们解决潜在的问题。 我总是喜欢用cping工具来进行网络监测。它的界面整洁,让我一目了然。重要的是,...

    如何高效使用测速脚本监测网络性能

    在互联网的快速发展中,网络测速变得越来越重要。作为一个互联网用户,了解自己的网络性能是否稳定,以及在不同时间与地点的表现,能帮助我们更好地选择服务和进行问题排查。网络速度直接影响了我们的在线体验,无论是看视频、玩游戏,还是进行远程办公,网络性能都扮演着至关重要的角色。 测速脚本出现在这样的背景下,它...

    iHerb优惠码使用指南:最大化你的购物折扣

    在现代生活中,网络购物已经成为很多人日常消费的一部分,尤其是像iHerb这样的电商平台,提供了丰富的天然保健品和生活必需品。对于我们消费者来说,iHerb优惠码就是一个能够让购物更加实惠的绝佳工具。 iHerb优惠码是一种特殊的代码,用户在结账时输入这些代码,就可以享受相应的折扣。无论是新用户还是老...

    提升美国家庭网络安全与光纤宽带普及的最佳策略

    在当今这个数字化时代,家庭网络的建设与发展显得愈发重要。美国家庭对于网络的依赖程度日渐加深,这不仅仅体现在上网购物、观看视频、游戏娱乐等日常活动中,也体现在工作和学习的方方面面。作为一个普通家庭,我们的生活节奏已经被网络所塑造,无论是为了保持与亲友的联系,还是获取最新的信息,都离不开一个稳定而高效的...

    主机类型与高性能配置详解,选择最适合你的主机方案

    主机的定义与分类 什么是主机? 当我们谈论“主机”这个词时,通常指的是计算机系统,特别是在网络环境中提供服务或资源的设备。我个人觉得主机不仅仅是实体的机器,而是指在网络中扮演着重要角色的一种技术资源。它可以执行各种任务,从存储数据到托管网站,再到运行应用程序,主机的功能几乎无所不包。可以想象,主机就...