当前位置: 首页 > news >正文

广州17做网站站长工具无忧

广州17做网站,站长工具无忧,当当网站开发论文,做emc的有哪些网站frameworks 之Socket Socket服务端1.创建Socket。2.绑定socket3.监听socket4.等待客户端连接5.读取或者写入给客户端 客户端1.创建Socket。2.连接服务端Socket3.读取或者写入给客户端4.关闭socket 演示代码 Epoll创建Epoll添加或删除Epoll等待消息返回Epoll演示代码 SocketPair…

frameworks 之Socket

  • Socket
    • 服务端
      • 1.创建Socket。
      • 2.绑定socket
      • 3.监听socket
      • 4.等待客户端连接
      • 5.读取或者写入给客户端
    • 客户端
      • 1.创建Socket。
      • 2.连接服务端Socket
      • 3.读取或者写入给客户端
      • 4.关闭socket
    • 演示代码
  • Epoll
    • 创建Epoll
    • 添加或删除Epoll
    • 等待消息返回Epoll
    • 演示代码
  • SocketPair
    • 创建socketPair
    • 设置对应的属性
    • 演示代码

Socket是应用层与TCP/IP协议族通信的中间软件抽象层。他作为Android 进程间的通信。
涉及到的类如下

  • frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

Socket

创建一个socket 需要几个步骤
服务端: socket -> bind -> listen -> accept -> read/write -> close
客户端: socket -> connect -> read/write -> close

服务端

1.创建Socket。

第一个参数为协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL**(或称AF_UNIX,Unix域socket,这个是我们的讲解重点)**、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址

第二个参数 指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET

第三个参数为 指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

int socketFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);

2.绑定socket

bind()函数就是将给这个描述字绑定一个名字。addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同。addrlen:对应的是地址的长度。

int bindResult = bind(socketFd,  (struct sockaddr *)&serviceAddr, serviceLen);

地址为抽象和文件类型。文件类型会生成一个文件在本地,抽象需要在地址前面加0,对应会生成@开头。可以用如下命令查询查看

netstat -an | grep 地址名称

3.监听socket

设置监听的最大连接个数

int listenerResult = listen(socketFd, SOCKET_NUMBER);

4.等待客户端连接

传入客户端的对象 和长度 由内核写入。等待客户端的连接。

int connectFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clintLen);

5.读取或者写入给客户端

通过 read 或者 write 函数跟客户端通信

		   int dataSize = read(connectFd, &buffer, sizeof(buffer));if (dataSize == 0){printf("客户端关闭连接\n");} else if (dataSize == -1){printf("读取异常\n");exit(1);} else {printf("客户端发送了: %s\n" ,buffer);for (int i = 0; i < sizeof(buffer); i++){buffer[i] = toupper(buffer[i]);}write(connectFd, buffer, sizeof(buffer));}

客户端

1.创建Socket。

int serviceFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);

2.连接服务端Socket

发起对服务端的连接,连接成功后 服务端 accept 方法将继续执行

int connectResult = connect(serviceFd, (struct sockaddr *)&clientAddr, clientLen);

3.读取或者写入给客户端

		int wirteResult = write(serviceFd, winBuffer, sizeof(winBuffer));printf("写入服务端数据 %i", wirteResult);// 阻塞读取服务端数据int readResult =read(serviceFd, winBuffer, sizeof(winBuffer));

4.关闭socket

close(serviceFd);

演示代码

服务端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// scoket相关
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// SOCKETD地址
#define SOCKET_SERVICE_ADDRESS "natvie_socket_test"
// 允许连接的长度
#define SOCKET_NUMBER 20
// 读取数据大小
#define BUFFER_SZIE 80/*** 主文件入口
*/
int main (void) {// socket 文件描述符int socketFd;// 客户端的socket 文件描述符int clintSocetFd;// socket 实体类struct sockaddr_un serviceAddr, clientAddr;// 地址长度socklen_t serviceLen; socklen_t clintLen;// 数据读取char buffer[BUFFER_SZIE];// 创建socketsocketFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);if (socketFd == -1){printf("创建 socket 失败\n");exit(1);}// 清空memset(&serviceAddr, 0 ,sizeof(sockaddr_un));serviceAddr.sun_family = AF_UNIX;// 设置地址strncpy(serviceAddr.sun_path, SOCKET_SERVICE_ADDRESS, sizeof(serviceAddr.sun_path) - 1);// 计算长度serviceLen = sizeof(serviceAddr.sun_family) + sizeof(serviceAddr.sun_path);// 绑定地址int bindResult = bind(socketFd,  (struct sockaddr *)&serviceAddr, serviceLen);if (bindResult == -1){printf("绑定 socket 失败\n");exit(1);}// 绑定成功后 需要监听int listenerResult = listen(socketFd, SOCKET_NUMBER);if (listenerResult == -1){printf("监听 socket 失败\n");exit(1);}printf("服务端 socket建立 等待连接\n");// 死循环等待连接while (1){// 等待接收客户端连接, 同时客户端的信息会写入该类, 会阻塞在这里clintLen = sizeof(struct sockaddr_un);int connectFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clintLen);if (connectFd == -1) {printf("监听 socket 失败\n");exit(1);}// 创建成功,循环读取消息while (1){// 0 为关闭 -1 为异常int dataSize = read(connectFd, &buffer, sizeof(buffer));if (dataSize == 0){printf("客户端关闭连接\n");} else if (dataSize == -1){printf("读取异常\n");exit(1);} else {printf("客户端发送了: %s\n" ,buffer);for (int i = 0; i < sizeof(buffer); i++){buffer[i] = toupper(buffer[i]);}write(connectFd, buffer, sizeof(buffer));}}}// 退出for循环 关闭socketprintf("服务端关闭连接\n");close(socketFd);return 0;
}

客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// scoket相关
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// SOCKETD地址
#define SOCKET_SERVICE_ADDRESS "natvie_socket_test"
// 允许连接的长度
#define SOCKET_NUMBER 20
// 读取数据大小
#define BUFFER_SZIE 80
// 输入最大行
#define MAXLINE 80int main(void) {// 客户端操作符int serviceFd;sockaddr_un clientAddr;// 地址长度socklen_t clientLen;// 从输入框输入流char winBuffer[BUFFER_SZIE];serviceFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);if (serviceFd == -1){printf("创建 socket 失败");exit(0);}// 清空数据memset(&clientAddr, 0, sizeof(struct sockaddr_un));// 赋值地址clientAddr.sun_family = AF_UNIX;strncpy(clientAddr.sun_path, SOCKET_SERVICE_ADDRESS, sizeof(clientAddr.sun_path) - 1);clientLen = sizeof(clientAddr);printf("socket地址: %s\n", clientAddr.sun_path);int connectResult = connect(serviceFd, (struct sockaddr *)&clientAddr, clientLen);if (connectResult == -1){perror("连接 socket 失败");exit(0);}printf("请输入对应的数据:");while (fgets(winBuffer, MAXLINE, stdin)){// 把读到的数据给服务端int wirteResult = write(serviceFd, winBuffer, sizeof(winBuffer));printf("写入服务端数据 %i", wirteResult);// 阻塞读取服务端数据int readResult =read(serviceFd, winBuffer, sizeof(winBuffer));if (readResult <= 0) {  printf("服务端异常或者已关闭\n");break;}else {  printf("接收到服务端的消息: %s \n",winBuffer);}printf("请输入对应的数据:");}close(serviceFd);return 0;   
}

Epoll

上面提到的socket 的 accept 和 read 等方法都是阻塞方法,等多客户端无法实现实时的读取和监听,如果每个客户端开对应的线程则比较耗资源。因此有了Epoll 等待唤醒。Epoll 有如下方法。

创建Epoll

需要传入一个数量,该数量大于0即可。并会返回一个文件描述符

// 创建 epoll, 参数size 实际没作用,但是要大于0 
int epollFd = epoll_create(EPOLL_SZIE);

添加或删除Epoll

第二参数控制 添加还是删除
第三个参数为需要监听的文件操作符
第四个参数为 epoll_event 类型
data.fd 可以存储对应的文件ID
events属性表示数据类型 EPOLLIN

 int addResult = epoll_ctl(epollFd, EPOLL_CTL_ADD, serviceFd, &epollEvent); 

等待消息返回Epoll

events参数传入事件数组,内核会对应写入的数组。可通过 events.data.fd 获取对应的客户端。
size 表示每次可以处理的最大事件数量
最后参数代表等待的事件,0为马上返回,-1为阻塞等待

 int eventNum = epoll_wait(epollFd, events, EPOLL_EVENT_MAX_SZIE, EPOLL_TIEM_OUT);

演示代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// scoket相关
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
// epoll 相关
#include <sys/epoll.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// SOCKETD地址
#define SOCKET_SERVICE_ADDRESS "epoll_socket_test"
// 允许连接的长度
#define SOCKET_NUMBER 20
// 读取数据大小
#define BUFFER_SZIE 80
// epoll大小
#define EPOLL_SZIE 80
// epoll消息大小
#define EPOLL_EVENT_MAX_SZIE 20
// epoll消息超时
#define EPOLL_TIEM_OUT -1// 采用抽象作用域
int main(void) {int serviceFd;sockaddr_un serviceAddr;socklen_t serviceLen, clientLen;char buffer[BUFFER_SZIE];serviceFd = socket(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL);if (serviceFd == -1) {perror("创建 socket 失败");exit(0);}memset(&serviceAddr, 0 , sizeof(struct sockaddr) - 1);serviceAddr.sun_family = AF_UNIX;// 这里采用抽象的协议, 第一位要给0serviceAddr.sun_path[0] = 0;strcpy(serviceAddr.sun_path + 1, SOCKET_SERVICE_ADDRESS);// serviceLen = sizeof(serviceAddr.sun_family) + strlen(SOCKET_SERVICE_ADDRESS) + 1;serviceLen = sizeof(serviceAddr.sun_family) + sizeof(serviceAddr.sun_path);printf("绑定的地址为:%s \n", serviceAddr.sun_path);// 绑定int bindResult = bind(serviceFd, (struct sockaddr *)&serviceAddr, serviceLen);if (bindResult == -1) {perror("绑定 socket 失败");exit(0);}int listenResult = listen(serviceFd, SOCKET_NUMBER);if (listenResult == -1) {perror("监听 socket 失败");exit(0);}// 创建 epoll, 参数size 实际没作用,但是要大于0 int epollFd = epoll_create(EPOLL_SZIE);if (epollFd == -1){perror("创建 epoll 失败");exit(0);}// 将对应的文件夹 添加 epoll中epoll_event epollEvent;/* *** 注意****epoll_data 是一个联合体结构成员,所有的成员公用一段内存,因此实际上只能保留一个成员它只会保存最后一个被赋值的成员,所以不要data.fd,data.ptr都赋值*/epollEvent.data.fd = serviceFd;epollEvent.events = EPOLLIN;// 循环检测 委托内核去处理// 当内核检测到事件到来时会将事件写到这个结构体数组里struct epoll_event events[EPOLL_EVENT_MAX_SZIE];int addResult = epoll_ctl(epollFd, EPOLL_CTL_ADD, serviceFd, &epollEvent); if (addResult == -1){perror("添加到 epoll 失败");exit(0);}printf("开始接收消息\n");while (1){// 等待有没消息返回// tiemOut 为0 马上返回 为-1 代表阻塞// maxevents:表示每次能处理的最大事件数,告之内核这个events有多大;这个maxevents的值不能大于创建epoll_create()时的size;int eventNum = epoll_wait(epollFd, events, EPOLL_EVENT_MAX_SZIE, EPOLL_TIEM_OUT);printf("收到消息数量: %i \n", eventNum);for (int i = 0; i < eventNum; i++){// 有连接请求到来,走到这里if (events[i].data.fd == serviceFd){// 客户端信息填充struct sockaddr_un clientAddr;socklen_t clientLen = sizeof(clientAddr);int connectFd = accept(serviceFd, (struct sockaddr *)&clientAddr, &clientLen);if (connectFd == -1){perror("接收客户端失败");exit(0);}printf("接收到新的客户端\n");//将用于通信的文件描述符挂到epoll树上epollEvent.data.fd = connectFd;epollEvent.events = EPOLLIN;epoll_ctl(epollFd, EPOLL_CTL_ADD, connectFd, &epollEvent);} else{// 其他的为客户端发送的值// 通信也有可能是写事件if (events[i].events & EPOLLOUT){//这里先忽略写事件continue;}char buf[1024]={0};int count = read(events[i].data.fd, buf, sizeof(buf));if (count == 0){// 关闭了客户端要关闭printf("收到客户端关闭");close(events[i].data.fd);epoll_ctl(epollFd, EPOLL_CTL_DEL, events[i].data.fd, NULL);continue;}if (count == -1){perror("接收消息异常退出");exit(0);}printf("收到了消息事件:%s \n", buf);for (int i = 0; i < sizeof(buf); i++){buf[i] = toupper(buf[i]);}write(events[i].data.fd, buf, sizeof(buf));}}}close(serviceFd);return 0;
}

SocketPair

如果是单纯1对1通讯,可通过 socketPair 快速建立服务端和客户端

创建socketPair

创建一个数组存储对应的ID,创建的socket 会放在该数组里面

int socketFds[2];
// 创建socke 第一个作为服务端 第二个作为客户端
int result = socketpair(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL, socketFds);

设置对应的属性

以下代码设置对应的缓冲区

socklen_t len = sizeof(BUFFER_SZIE);
setsockopt(socketFds[0], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);
setsockopt(socketFds[0], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);
setsockopt(socketFds[1], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);
setsockopt(socketFds[1], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);

演示代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <sys/types.h>
#include <sys/socket.h>#include <unistd.h>// 协议域
int SOCKET_DOMIAN = AF_UNIX;
// 类型
int SOCKET_TYPE = SOCK_STREAM;
// 协议,常用tcp udp
int SOCKET_PROTOCOL = 0;
// 缓存区大小
int BUFFER_SZIE = 1024;int main(void) {int socketFds[2];// 创建socke 第一个作为服务端 第二个作为客户端int result = socketpair(SOCKET_DOMIAN, SOCKET_TYPE, SOCKET_PROTOCOL, socketFds);if (result == -1){perror("创建 socketPair 错误");exit(0);}/*** 第一个参数socket是套接字描述符。* 第二个参数level是被设置的选项的级别,如果想要在套接字级别上设置选项,就必须把level设置为 SOL_SOCKET。* option_name指定准备设置的选项,option_name可以有哪些取值,这取决于level,在套接字级别上(SOL_SOCKET)* 主要设置缓存区大小*/socklen_t len = sizeof(BUFFER_SZIE);setsockopt(socketFds[0], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);setsockopt(socketFds[0], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);setsockopt(socketFds[1], SOL_SOCKET, SO_SNDBUF, &BUFFER_SZIE, len);setsockopt(socketFds[1], SOL_SOCKET, SO_RCVBUF, &BUFFER_SZIE, len);int pid = fork();printf("孵化出来的进程号为 %i \n", pid);// 在子进程为0if (!pid){printf("执行子进程\n");// 为子进程close(socketFds[0]);int count = 0;while (1){// 休眠一秒sleep(1);// 发送给服务端端write(socketFds[1], &count, sizeof(count));int size = read(socketFds[1], &count, sizeof(count));printf("收到服务端数据 %i \n", count);++count;}} else {printf("执行父进程\n");// 为父进程close(socketFds[1]);int count = 0;while (1){   // 读取客户端数据int size = read(socketFds[0], &count, sizeof(count));if (read <= 0){perror("客户端异常退出 \n");exit(0);}printf("收到客户端数据 %i \n", count);++count;// 发送给客户端write(socketFds[0], &count, sizeof(count));}}
}
http://www.tj-hxxt.cn/news/19532.html

相关文章:

  • 深圳CSS3网站建设价格爱站网关键词密度
  • 婚车租赁中山seo
  • 学服装设计培训机构seo搜索引擎优化教程
  • 桂林建站合肥百度关键词排名
  • 做的网站百度找不到了如何让自己网站排名提高
  • 网站建设方案对比报告深圳网站优化软件
  • wordpress 裁剪图片工具seo
  • 电子毕业设计代做网站李飞seo
  • 家装设计网站怎么做宠物美容师宠物美容培训学校
  • 日报做的地方网站简述网络营销的特点及功能
  • 网站空间根目录百度集团官网
  • 怎么做军事小视频网站百度seo怎么查排名
  • 连云港专业网站制作重庆seo报价
  • 做ppt一般在什么网站好2023知名品牌营销案例100例
  • 淄博网站制作设计杭州做网站的公司排行
  • 公司登记兰州seo关键词优化
  • 域名备案和网站备案的区别seo关键词优化推广哪家好
  • 如何建立网站模板全国疫情最新情况公布
  • 百合视频做爰视频网站品牌运营具体做什么
  • java开发网站南京百度快速排名优化
  • 成都疫情越来越严重了贵州二级站seo整站优化排名
  • 网站建设与管理李洪心第三方关键词优化排名
  • 网站ui设计是什么陕西seo关键词优化外包
  • seo信息编辑招聘长沙网站优化推广方案
  • 深圳做网站找哪家好比百度还强大的搜索引擎
  • 网站图标代码百度搜一下
  • 做暧暖网站百度在线识图
  • 楼盘网站开发站群seo技巧
  • 网站开发设计文档企业网站的域名是该企业的
  • 什么app做网站收录网站排名