网络编程(2)Socket同步非阻塞工作模式

        同步非阻塞模式比前面说的那个同步阻塞模式要高些,虽然高得有限.在这种模式下,send或recv函数会设为MSG_DONTWAIT,

即非阻塞,即便没有值,就略过继续做后面的事。比如有多个socket时,可以去查看其他socket有没有可以接收的数据。然后再反复检查前面的执行情况,直到有数据为止。

      这种模式优点是不阻塞了,但消耗的系统资源太多,因为它要不停的去检查,做了很多没有必要的调用。

一。Socket客户端例子
所用到的头文件在 网络编程(1)跨平台的Socket同步阻塞工作模式例子 中有.

代码如下:

/*************************************************
Author: xiongchuanliang
Description: 同步非阻塞工作模式例子_客户端代码
编译命令:
Linux:
g++ -o tcpclientnoblk tcpclientnoblk.cpp -m64 -I./common
**************************************************/

// 客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "initsock.h"
#include "common.h"

int main(int argc, char* argv[])
{	  
	 int sclient = 0;	//连接服务端的套接字
	 int flags =  0;	//fcntl返回标识
	 int recvbytes = 0; //服务端返回的数据长度
	 char recvData[MAXDATASIZE] = {0};	//保存服务端返回的数据

	 //取出传入参数
	 const size_t MaxLen = 500;
	 char  testMsg[MaxLen]={0};

	 if(argc < 3)
	 {		
	    printf("Usage:%s [ip address] [any string]\n",argv[0]);
		exit(EXIT_FAILURE);
	 }else{
		strncpy(testMsg,argv[2],strlen(argv[2]));		
		printf("Message: %s \n",testMsg);
	 }

	//建立套接字
	sclient = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(sclient == INVALID_SOCKET)
	{
		PrintError("invalid() failed");
		exit(EXIT_FAILURE);
	}

	//指定要连接的服务器地址和端口
	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVPORT);
	inet_pton(AF_INET, argv[1], &server_addr.sin_addr);	//用户输入的ip参数		
	memset(&(server_addr.sin_zero),0,8);

	//设为非阻塞模式
	//方法一:
	 flags = fcntl(sclient, F_GETFL, 0); //得到套接字描述符标识位
	 if(flags < 0)
	 {
		PrintError("fcntl() failed");
		exit(EXIT_FAILURE);
	 }
	 fcntl(sclient, flags|O_NONBLOCK); // 更改套接字描述符标识位

	 //方法二:
	 // #include <unistd.h>
	 // #include <sys/ioctl.h>
	 // ioctl(sclient,FIONBIO,&flags);

	//将套接字连接上服务器
	if( connect(sclient,(struct sockaddr *)&server_addr,sizeof(struct sockaddr) ) == -1)
	{
		PrintError("connect() failed");
		exit(EXIT_FAILURE);
	}
	
	//同步非阻塞模式--发送数据到服务端
	 while(send(sclient,testMsg,strlen(testMsg),MSG_DONTWAIT) == -1)
	 {
		  sleep(10);
		  printf("send() sleep(10)\n");
	 }
	 printf("send success!\n");
	
	//同步非阻塞模式--接收返回的数据	
	while( (recvbytes = recv(sclient,recvData,MAXDATASIZE,MSG_DONTWAIT)) == -1)
	{
		  sleep(10);
		  printf("recv() sleep(10)\n");
	 }
	 printf("recv success!\n");

	if( recvbytes == 0)
	{
		printf("recv() no data!\n");
	}else if( recvbytes < 0)
	{
		PrintError("recv() failed");
	}else {
		recvData[recvbytes]='\0';
		printf("recv:%s\n",recvData);	
	}

	//关闭套接字,结束此次TCP会话
	close(sclient);

	exit(EXIT_SUCCESS);
}


二。总结
设为非阻塞模式,主要就是更改Socket的属性。并设置 MSG_DONTWAIT.
更改Socket属性提供了两种方法:
方法一:
         flags = fcntl(sclient, F_GETFL, 0); //得到套接字描述符标识位
	 if(flags < 0)
	 {
		PrintError("fcntl() failed");
		exit(EXIT_FAILURE);
	 }
	 fcntl(sclient, flags|O_NONBLOCK); // 更改套接字描述符标识位

方法二:
#include <unistd.h>
	  #include <sys/ioctl.h>
	  ioctl(sclient,FIONBIO,&flags);
   

   同时,在代码中,可以看到send和recv都放在while中,不停的检查返回值。效率并不高。


MAIL: xcl_168@aliyun.com

BLOG:http://blog.csdn.net/xcl168


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值