socket在创建的时候默认是阻塞的,要想设置为非阻塞的有以下几种方法:
1.ioctl 和 fcntl 设置已经创建socket的fd
ioctl用于设备控制
#include
int ioctl(int fd, unsigned long request, ...);
fcntl用于文件控制
#include
#include
int fcntl(int fd, int cmd, ... /* arg */ );
通过下面方式设置:
flags = fcntl(sfd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sfd, F_SETFL, flags);
2.在创建socket的时候设置
int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
3.accept4
int accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags);
flags 设置成 SOCK_NONBLOCK,这种方式是在服务端。
服务端设置5秒后再接收数据:
#include
#include
#include
#include
#include
#include
int main(int argc, char* argv[]){
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd < 0){
printf("create socket failed!, errno=%d\n",errno);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(8080);
int ret;
ret = bind(fd, (struct sockaddr*) &addr, sizeof(addr));
if(ret == -1){
printf("bind failed!, errno=%d",errno);
close(fd);
}
ret = listen(fd, SOMAXCONN);
if(ret == -1){
printf("listen failed!, errno=%d",errno);
}
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
int afd = accept(fd, (struct sockaddr*) &clientaddr, &clientaddrlen);
if(afd != -1){
printf("A client connected!,ip=%s,port=%d\n",inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
char buf[256] = {0};
sleep(5);
ret = recv(afd, buf, 256, 0);
if(ret > 0){
printf("recv %d byte:%s\n",ret,buf);
}
else if(ret == -1){
printf("recv error!,errno=%d\n",errno);
}
else{
printf("client disconnect!\n");
}
}
else{
printf("accept failed!,errno=%d\n",errno);
}
}
客户端设置非阻塞,验证一下send非阻塞的现象:
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char* argv[]){
if(argc != 3){
printf("please input IP port\n");
}
char* ip = argv[1];
unsigned int port = atoi(argv[2]);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd < 0){
printf("create socket failed!, errno=%d\n",errno);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
int ret;
ret = connect(fd, (struct sockaddr*) &addr, sizeof(addr));
if(ret == -1){
printf("connect failed!, errno=%d",errno);
}
else{
//连接成功后将fd设置为非阻塞
int flags = fcntl(fd, F_GETFL);
flags |= O_NONBLOCK;
ret = fcntl(fd, F_SETFL, flags);
if(ret == -1){
printf("set O_NONBLOCK failed!,errno=%d\n",errno);
}
char *buf = "hello, I am a client!";
int cnt = 0;
while(1){
ret = send(fd, buf, strlen(buf), 0);
if(ret > 0){
cnt++;
printf("send %d byte:%s,cnt = %d\n",ret,buf,cnt);
}
else if(ret == -1){
if(errno == EAGAIN){
printf("send try again\n");
sleep(1);
continue;
}
else
printf("send error!,errno=%d\n",errno);
}
else{
printf("server disconnect!\n");
}
}
}
}