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

网站建设上海零基础怎么做电商

网站建设上海,零基础怎么做电商,韶关建设局网站,武汉建设局官网在Linux下,一般使用read & write函数完成数据IO,因为Linux下的套接字,可视为文件,其操作方式与文件类似,当套接字分配之后,会为其分配对应的文件描述符。在Windows下,则需要使用recv & …

在Linux下,一般使用read & write函数完成数据IO,因为Linux下的套接字,可视为文件,其操作方式与文件类似,当套接字分配之后,会为其分配对应的文件描述符。在Windows下,则需要使用recv & send函数完成数据IO

1. Linux下的recv & send 函数

Linux下的recv 和send函数与windows下的其实并无差别,其参数顺序,含义,使用方法完全相同,与实际区别不大:

#include <sys/socket.h>ssize_t send(int sockfd, const void* buf, size_t nbytes, int flags);/*
sockfd: 与数据传输对象连接的套接字文件描述符
buf:    待传输数据的缓冲区
nbytes: 待传输的字节数
flags:  传输数据时指定的可选项信息
*/
#include <sys/socket.h>ssize_t recv(int sockfd, const void* buf, size_t nbytes, int flags);/*
sockfd: 与数据接收对象连接的套接字文件描述符
buf:    待接收数据的缓冲区
nbytes: 待接收的字节数
flags:  接收数据时指定的可选项信息
*/

send()和recv()函数的最后一个参数表示数据收发的可选项,该选项可使用位或运算同时传递多个信息:

可选项含义sendrecv
MSG_OOB用于传输带外数据(out-of-band data)
MSG_PEEK验证输入缓冲中是否存在接收的数据
MSG_DONTROUTE数据传输过程中不参照路由表,在本地网络中寻找目的地
MSG_DONTWAIT调用IO函数时不阻塞,用于使用非阻塞IO
MSG_WAITALL防止函数返回,直到接收全部请求的字节数

1.1 MSG_OOB发送紧急消息:

MSG_OOB可用于创建特殊发送方法和特殊发送通道,发送带外数据紧急消息。使用MSG_OOB收发消息例程如下所示:

客户端client.cpp代码:

/*send the msg oob data
*/#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define BUFF_SIZE    30#define RECV_ADDRESS    "127.0.0.1"
#define RECV_PORT       54100void error_handler(char* message);int main(int argc, char* argv[])
{int sock;struct sockaddr_in recvAddr;sock = socket(PF_INET, SOCK_STREAM, 0);memset(&recvAddr, 0, sizeof(recvAddr));recvAddr.sin_family = AF_INET;recvAddr.sin_addr.s_addr = inet_addr(RECV_ADDRESS);        // 地址recvAddr.sin_port = htons(RECV_PORT);                // 端口printf("Connecting to server......\n");if (connect(sock, (struct sockaddr*)&recvAddr, sizeof(recvAddr)) == -1){char message[50];sprintf(message, "Failed to connect to address: %s  %d", RECV_ADDRESS, RECV_PORT);error_handler(message);}printf("Successfully connectiing server.\n");write(sock, "1234", strlen("1234"));send(sock, "1131", strlen("1131"), MSG_OOB);     // 紧急发送消息,带外数据 out of band (OOB)write(sock, "333", strlen("333"));send(sock, "991", strlen("991"), MSG_OOB);       // 紧急发送消息,带外数据 out of band (OOB)close(sock);return 0;
}void error_handler(char* message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}

服务端server.cpp代码:

/* server receive data */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>#define BUFF_SZIE   30
#define SERVER_ADDRESS    "127.0.0.1"
#define SERVER_PORT       54100void error_handler(char* message);
void urge_handler(int signo);int server_sock;
int client_sock;int main(int argc, char* argv[])
{struct sockaddr_in serverAddr, clientAddr;int strLen, state;socklen_t addrSize = sizeof(serverAddr);struct sigaction act;char buf[BUFF_SZIE];memset(buf, 0, BUFF_SZIE);// 信号初始化act.sa_handler = urge_handler;       // 信号处理函数sigemptyset(&act.sa_mask);act.sa_flags = 0;server_sock = socket(PF_INET, SOCK_STREAM, 0);memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);serverAddr.sin_port = htons(SERVER_PORT);if (bind(server_sock, (struct sockaddr*)&serverAddr, addrSize) == -1){error_handler("Failed to bind()\n");}listen(server_sock, 5);client_sock = accept(server_sock, (struct sockaddr*)&serverAddr, &addrSize);if (client_sock == -1){error_handler("Failed to accept new connection from client.\n");}fcntl(client_sock, F_SETOWN, getpid());state = sigaction(SIGURG, &act, 0);       // 注册信号while ((strLen = recv(client_sock, buf, BUFF_SZIE - 1, 0)) != 0){/* code */if (strLen == -1)continue;char content[2*BUFF_SZIE];memset(content, 0, 2*BUFF_SZIE);sprintf(content, "Receive buffer is : %s\n", buf);puts(content);memset(buf, 0, BUFF_SZIE);}return 0;
}void error_handler(char* message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}/*如果客户端调用了紧急发送带外数据的函数,则系统会产生SIGURGE信号,并调用注册的信号处理函数进行处理
*/
void urge_handler(int signo)
{char buff[BUFF_SZIE];memset(buff, 0, BUFF_SZIE);int recvLen = recv(client_sock, buff, BUFF_SZIE - 1, MSG_OOB);printf("Urge Message: %s\n", buff);
}

输出:

需要介绍一下fcntl函数的作用:

fcntl函数可以用来对已打开的文件描述符进行各种控制操作以改变已打开文件的的各种属性;

介绍:fcntl 函数 - 天池渔隐 - 博客园 (cnblogs.com)

    fcntl(client_sock, F_SETOWN, getpid());

上述语句含义表示:文件描述符client_sock指向的套接字引发的SIGURG信号处理进程将变为getpid函数返回值用作ID的进程。

上述描述中的处理SIGURG信号表示的是“调用SIGURG信号处理函数”。在多进程服务器中,多个进程可以共同拥有一个套接字文件描述符。例如,通过fork函数创建了子进程,并同时复制了文件描述符,此时如果发生了SIGURG信号,应该调用哪个进程的信号处理函数就成为了一个问题。因此,在处理信号的时候,必须指定哪一个进程来处理信号。在上述代码中,处理SIGURG信号的时候必须指定处理信号的进程,而getpid函数返回调用此函数的进程。则fctl语句指定的是当前进程作为处理SIGURG信号的主体。

*通过观察程序的输出结果,发现通过MSG_OOB可选项传递数据时,只会返回一个字节;通过MSG_OOB可选项传输数据时并不会加快数据的传输速度,而且通过信号处理函数读取传输过来的数据时,也只能读取到一个字节的数据,剩余的数据只能通未设置MSG_OOB可选项的普通输入函数进行读取。因为TCP不存在真正意义上的带外数据(Out of b band),真正意义上的带外数据需要通过单独的通信路径高速传输数据,TCP不提供这样的传输路径,仅是利用TCP的紧急模式进行传输。

检查输入缓冲区

同时设置MSG_PEEK和MSG_DONTWAIT选项,可以验证输入缓冲中是否存在接收的数据。设置MSG_PEEK选项并调用recv函数时,即使读取了输入缓冲中的数据,也不会将缓冲中的数据进行删除。此选项通常与MSG_DONTWAIT合作,用于调用以非阻塞方式验证待读取数据是否存在。示例代码如下所示:

客户端代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define  ADDRESS   "127.0.0.1"
#define  PORT      38400int main(int argc, char** argv)
{int sock;struct sockaddr_in address;   sock  = socket(PF_INET, SOCK_STREAM, 0);memset(&address, 0, sizeof(address));address.sin_family = AF_INET;address.sin_addr.s_addr = inet_addr(ADDRESS);address.sin_port = htons(PORT);if (connect(sock, (struct sockaddr*)&address, sizeof(address))){printf("Failed to connect to server.\n");return -1;}write(sock, "3456", strlen("3456"));close(sock);return 0;
}

服务端代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define  ADDRESS      "127.0.0.1"
#define  PORT         38400
#define  BUFF_SIZE    30int main(int argc, char** argv)
{int serverSock, clientSock;struct sockaddr_in servAddr, clientAddr;socklen_t addrSize = sizeof(servAddr);char buffer[BUFF_SIZE];memset(buffer, 0, BUFF_SIZE);memset(&servAddr, 0, sizeof(servAddr));memset(&clientAddr,0 , sizeof(clientAddr));serverSock = socket(PF_INET, SOCK_STREAM, 0);servAddr.sin_family = AF_INET;servAddr.sin_addr.s_addr = inet_addr(ADDRESS);servAddr.sin_port = htons(PORT);int bindRes = bind(serverSock, (struct sockaddr*)&servAddr, sizeof(servAddr));if (bindRes == -1){printf("Failed to bind the socket.");return -1;}// 开始监听listen(serverSock, 5);clientSock = accept(serverSock, (struct sockaddr*)&servAddr, &addrSize);while (true){/* code */int recvLen = recv(clientSock, buffer, BUFF_SIZE-1, MSG_PEEK | MSG_DONTWAIT);if (recvLen > 0)break;}printf("Buffer content: %s\n", buffer);printf("Clearing the buffer.\n");memset(buffer, 0, BUFF_SIZE);recv(clientSock, buffer, BUFF_SIZE-1, 0);printf("Read again: %s\n", buffer);close(clientSock);close(serverSock);return 0;
}

运行结果:

 可以看到在第一次读取完缓冲区中的数据之后,并未将数据进行清除,还可再次读取数据

readv函数和writev函数 (矢量IO操作)

”这两个函数主要用于对数据进行整合传输以及发送“

即writev函数可以将分散保存在多个缓冲区中的数据一并发送,通过readv函数可以由多个缓冲区分别接收,因此适当使用这个两个函数可减少IO函数的调用次数。

#include <sys/uio.h>ssize_t writev(int filedes, const struct iovec* iov, int iovcnt);

filedes: 表示数据传输对象的套接字文件描述符,但是该函数并不只限于套接字,因此可以向read函数一样向其传输文件或标准输出描述符。

返回值:失败时返回-1,成功时返回发送的字节数

iov: iovec结构体数组的地址值,结构体iovec中包含待发送数据的位置和大小信息

iovcnt:  iovec结构体数组的长度

iovec结构体的声明如下所示:

struct iovec
{void* iov_base;     // 缓冲地址size_t iovlen;      // 缓冲大小
}

示例代码如下:

#include <stdio.h>
#include <sys/uio.h>int main(int argc, char* argv[])
{struct iovec vec[2];char buf1[] = "sdkjfcdc";char buf2[] = "4613241356";vec[0].iov_base = buf1;vec[0].iov_len  = 3;vec[1].iov_base = buf2;vec[1].iov_len  = 5;int lengtn = writev(1, vec, 2);puts("");     // 输出一个换行printf("write length is: %d", lengtn);return 0;
}

输出结果:

readv函数的定义:

#include <sys/uio.h>ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);// 返回值:失败时返回-1,成功时返回接受到的总字节数
filedes:传递接收数据的文件(套接字)描述符

示例代码:

#include <stdio.h>
#include <sys/uio.h>#define BUFF_SIZE  100int main(int argc, char* argv[])
{struct iovec vec[2];char buf1[BUFF_SIZE] = {0};char buf2[BUFF_SIZE] = {0};vec[0].iov_base = buf1;vec[0].iov_len  = 5;vec[1].iov_base = buf2;vec[1].iov_len  = BUFF_SIZE;int lengtn = readv(0, vec, 2);puts("");     // 输出一个换行printf("read length is: %d\n", lengtn);printf("First message is : %s\n", vec[0].iov_base);printf("Second message is : %s\n", vec[1].iov_base);printf("");return 0;
}

输出结果:

使用场景:需要传输的数据位于不同的缓冲区时,可以通过1次writev函数调用替代多次write函数调用,提高效率。同样,需要将输入缓冲区中的数据读入不同的位置时,也可以利用1次readv函数进行读取,从而提高效率。仅从C语言的角度来讲,减少函数的调用次数,也能相应的提高性能,但其更大的意义在于减少了数据包的个数,因此writev函数在不在Nagle算法时更有价值。

如果将不同位置数据按照发送的顺序,移动到一个大数组,再调用write一次发送,达到的效果与writev函数相同,但是很明显writev函数更为方便~

---------------------------------------end-------------------------------------------------

http://www.dtcms.com/wzjs/32894.html

相关文章:

  • 企业网站怎样做seo优化 应该如何做seo是什么职业做什么的
  • 短网址工具百度推广优化是什么?
  • 安徽网站优化怎么做aso优化吧
  • 西宁网站建设制作公司北京seo招聘
  • 免费网页奖励自己游戏网站合肥百度推广公司哪家好
  • 网站没有索引量是什么黑帽seo技巧
  • Wordpress能更新到最新版本济南百度推广优化
  • 室内设计平面布置图搜索引擎优化的简称是
  • 兰州网站建设优化制作公司制作网站平台
  • 郑州网站优化公司平台品牌营销策略案例
  • 北京网站制作快速的网站设计制作
  • 网站seo优化怎么做网站排名优化怎么做
  • 成都网站建设 四川冠辰高级搜索入口
  • 网站委托建设服务协议可以入侵的网站
  • 网站建设公司网站建设专业品牌网络营销成功案例3篇
  • 做房产中介网站网上找客户有什么渠道
  • 电子商务网站建设的核心爱站网关键词密度查询
  • ssh jsp做网站友链交换有什么作用
  • 荆州公司做网站百度做推广一般要多少钱
  • 志愿服务网站建设方案web制作网站的模板
  • 做网站的难点互联网营销方法有哪些
  • 东莞网站建设都找菲凡网络网站收录提交
  • 网页设计软件appwin7系统优化软件
  • 注册电气师在哪个网站做变更产品推广方案ppt模板
  • 建立网络专题网站架构上海快速优化排名
  • wordpress百度商桥seo如何优化
  • 电脑端网站一般做多宽最好百度竞价是什么意思
  • 8469网站宁波百度快照优化排名
  • 卫计网站建设工作计划网站开发北京公司
  • 做电商自建网站怎样seo外链