之前一直用linux中的read/write函数进行socket描述符的读写,而在windows中用recv/send进行socket的读写,其实在linux中也有自己的recv/send函数,同样可以进行IO端口的读写操作。

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

       recvsend函数的原型和windows中基本类似,这里主要介绍下其最后一个参数flags,用于设置接收数据时指定的可选项信息。


    在recv函数中同时设置MSG_PEEKMSG_DONTWAIT选项,以验证输入缓存上是否存在接收的数据。recv中设置了MSG_PEEK即使读取了输入缓冲的数据也不会被删除一次选项经常和MSG_DONTWAIT一起使用以非阻塞的方式验证输入缓冲数据是否存在。

peek_send.c:

#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>

void error_handling(char* message);

int main(int argc,char* argv[])
{
    int sock;
    struct sockaddr_in serv_addr;
    if(argc!=3)
    {
        printf("Usage %s <address> <port>",argv[0]);
        exit(1);
    }
    //创建socket
    sock=socket(AF_INET,SOCK_STREAM,0);
    //准备地址信息
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
    serv_addr.sin_port=htons(atoi(argv[2]));
    //连接服务器
    if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)
            error_handling("connect error");
    write(sock,"123",strlen("123"));
    return 0;
}

void error_handling(char* message)
{
    fputs(message,stderr);    
    fputc('\n',stderr);
    exit(1);
}

  客户端实现功能向服务器发送一个字符串”123”。

peek_recv.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<string.h>

#define BUF_SIZE 30

void error_handling(char* message);


int main(int argc,char* argv[])
{
    int serv_sock,clnt_sock;
    struct sockaddr_in serv_addr,clnt_addr;
    int clnt_addr_sz;
    int str_len;
    char buf[BUF_SIZE];
    if(argc!=2)
    {
        printf("Usage %s <port>\n",argv[0]);
        exit(1);
    }
    //创建socket
    serv_sock=socket(AF_INET,SOCK_STREAM,0);
    //设置地址
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_addr.sin_port=htons(atoi(argv[1]));
    //绑定
    if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)
            error_handling("bind error");
    //开启监听
    listen(serv_sock,5);
    //接收链接
    clnt_addr_sz=sizeof(clnt_addr);
    clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_sz);
    
    while(1)
    {
        str_len=recv(clnt_sock,buf,BUF_SIZE-1,MSG_PEEK|MSG_DONTWAIT);
        if(str_len>0)
                break;
    }
    buf[str_len]=0;
    puts(buf);
    str_len=recv(clnt_sock,buf,BUF_SIZE-1,0);
    buf[str_len]=0;
    puts(buf);
    return 0;
}
void error_handling(char* message)
{
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}

   服务器端对通过设置MSG_PEEK|MSG_DONTWAIT选项输入缓冲区进行了检查,如果发现存在数据进行读取


Github位置:

https://github.com/HymanLiuTS/NetDevelopment

克隆本项目:

git clone git@github.com:HymanLiuTS/NetDevelopment.git

获取本文源代码:

git checkout NL17


Logo

更多推荐