网络编程(17)—— 使用recv检查输入缓存是否有数据
之前一直用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,
之前一直用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);
recv和send函数的原型和windows中基本类似,这里主要介绍下其最后一个参数flags,用于设置接收数据时指定的可选项信息。
在recv函数中同时设置MSG_PEEK和MSG_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
更多推荐
所有评论(0)