Loadrunner 进行SOCKET并发测试遇到问题

<p>我对一个协议进行了封装,希望能在loadrunner下调用。结果调用收包函数的时候老是压不上去。</p>
<p>函数大致内容如下</p>
<p><br>extern "C" LRDLLTEST_API int receive_version_data(int sockfd)<br>{<br>char* receiveBuf = (char *)malloc(1024);<br>memset(receiveBuf,0,1024);</p>
<p>int n = recv(sockfd,(char *)receiveBuf,1024,0);</p>
<p>free(receiveBuf);</p>
<p>return n;</p>
<p>}</p>
<p></p>
<p>经过反复的验证,网上查资料终于发现</p>
<p>int n = recv(sockfd,(char *)receiveBuf,1024,0);</p>
<p>语句有问题</p>
<p>;</p>
<p>经修改如下:</p>
<p>int n = recv(sockfd,(char *)receiveBuf,1024,MSG_PEEK);</p>
<p></p>
<p></p>
<p>参阅资料如下:</p>
<p>旦,我们建立好了tcp连接之后,我们就可以把得到的fd当作文件描述符来使用。<br>由此网络程序里最基本的函数就是read和write函数了。<br>ssize_t write(int fd, const void*buf,size_t nbytes);<br><span class="f14" style="color: #000000;">write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量. 在网络程序中,当我们向套接字文件描述符写时有两可能. </span><br><span class="f14" style="color: #000000;"><span style="color: #ff0000;">1)write的返回值大于0,表示写了部分或者是全部的数据. 这样我们用一个while循环来不停的写入,但是循环过程中的buf参数和nbyte参数得由我们来更新。也就是说,网络写函数是不负责将全部数据写完之后在返回的。</span><br>2)返回的值小于0,此时出现了错误.我们要根据错误类型来处理. </span><br><span class="f14" style="color: #000000;">如果错误为EINTR表示在写的时候出现了中断错误. <br>如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接). <br>为了处理以上的情况,我们自己编写一个写函数来处理这几种情况. </span><br><br><span class="f14"><span style="color: #cccccc;"><span style="color: #000000;">int my_write(int fd,void *buffer,int length) <br>{ <br>int bytes_left; <br>int written_bytes; <br>char *ptr; <br><br>ptr=buffer; <br>bytes_left=length; <br>while(bytes_left>0) <br>{ <br> /* 开始写*/ <br> written_bytes=write(fd,ptr,bytes_left); <br> if(written_bytes<=0) /* 出错了*/ <br> { <br> if(errno==EINTR) <span style="color: #ff0000;">/* 中断错误 我们继续写*/ </span><br> written_bytes=0; <br> else<span style="color: #ff0000;">/* 其他错误 没有办法,只好撤退了*/ </span><br> return(-1); <br> } <br> bytes_left-=written_bytes; <br> ptr+=written_bytes;<span style="color: #ff0000;">/* 从剩下的地方继续写 */ </span><br>} <br>return(0); <br>} <br><br></span></span></span><span class="f14" style="color: #000000;">读函数read <br>ssize_t read(int fd,void *buf,size_t nbyte) <br>read函数是负责从fd中读取内容.当读成功 时,read返回实际所读的字节数,如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误.如果错误为EINTR说明读是由中断引起 的, 如果是ECONNREST表示网络连接出了问题. 和上面一样,我们也写一个自己的读函数. <br><br>int my_read(int fd,void *buffer,int length) <br>{ <br>int bytes_left; <br>int bytes_read; <br>char *ptr; <br><br>bytes_left=length; <br>while(bytes_left>0) <br>{ <br> bytes_read=read(fd,ptr,bytes_read); <br> if(bytes_read<0) <br> { <br> if(errno==EINTR) <br> bytes_read=0; <br> else <br> return(-1); <br> } <br> else if(bytes_read==0) <br> break; <br> bytes_left-=bytes_read; <br> ptr+=bytes_read; <br>} <br>return(length-bytes_left); <br>}<br><br></span><span class="f14"><span style="color: #cccccc;"><span style="color: #000000;">数据的传递 <br>有了上面的两个函数,我们就可以向客户端或者是服务端传递数据了.比如我们要传递一个结构.可以使用如下方式 <br><br>/* 客户端向服务端写 */ <br><br>struct my_struct my_struct_client; <br>write(fd,(void *)&my_struct_client,sizeof(struct my_struct); <br><br>/* 服务端的读*/ <br>char buffer[sizeof(struct my_struct)]; <br>struct *my_struct_server; <br>read(fd,(void *)buffer,sizeof(struct my_struct)); <br>my_struct_server=(struct my_struct *)buffer; <br><br>在网络上传递数据时我们一般都是把数据转化为char类型的数据传递.接收的时候也是一样的 注意的是我们没有必要在网络上传递指针(因为传递指针是没有任何意义的,我们必须传递指针所指向的内容)<br><br><br></span></span></span>6.1 recv和send <br><span style="color: #ff0000;">recv和send函数提供了和read和write差不多的功能.不过它们提供 了第四个参数来控制读写操作. </span><br><br>int recv(int sockfd,void *buf,int len,int flags) <br>int send(int sockfd,void *buf,int len,int flags) <br><br>前面的三个参数和read,write一样,第四个参数可以是0或者是以下的组合 <br>_______________________________________________________________ <br>| MSG_DONTROUTE | 不查找表 | <br>| MSG_OOB | 接受或者发送带外数据 | <br>| MSG_PEEK | 查看数据,并不从系统缓冲区移走数据 | <br>| MSG_WAITALL | 等待所有数据 | <br>|--------------------------------------------------------------| <br><br>MSG_DONTROUTE:是send函数使用的标志.这个标志告诉IP.目的主机在本地网络上面,没有必要查找表.这个标志一般用网络诊断和路由程序里面. <br>MSG_OOB:表示可以接收和发送带外的数据.关于带外数据我们以后会解释的. <br><br>MSG_PEEK:是recv函数的使用标志,<span style="color: #ff0000;">表示只是从系统缓冲区中读取内容,而不清除系统缓冲区的内容</span>.这样下次读的时候,仍然是一样的内容.一般在有多个进程读写数据时可以使用这个标志. <br><br>MSG_WAITALL<span style="color: #ff0000;">是recv函数的使用标志,表示等到所有的信息到达时才返回.使用这个标志的时候recv回一直阻塞,直到指定的条件满足,或者 是发生了错误. 1)当读到了指定的字节时,函数正常返回.返回值等于len 2)当读到了文件的结尾时,函数正常返回.返回值小于len 3)当操作发生错误时,返回-1,且设置错误为相应的错误号(errno) </span></p>
<div>
<div class="wikitext">
<p class="tightenable top"><span style="color: #ff0000;">MSG_NOSIGNAL</span> is a flag used by send() in some implementations of the Berkeley sockets <a class="wiki" href="http://www.wlug.org.nz/API">API</a>.</p>
<p class="tightenable">This flag requests that the implementation does not to send a <a class="wiki" href="http://www.wlug.org.nz/SIGPIPE">SIGPIPE</a> signal on errors on stream oriented sockets when the other end breaks the connection. The <a class="wiki" href="http://www.wlug.org.nz/EPIPE">EPIPE</a> error is still returned as normal.</p>
<p class="tightenable bottom">Though it is in some Berkely sockets APIs (notably Linux) it does not exist in what some refer to as the reference implementation, <a class="wiki" href="http://www.wlug.org.nz/FreeBSD">FreeBSD</a>, which instead uses a socket option <span class="wikiunknown"><span style="text-decoration: underline;">SO_NOSIGPIPE</span><a title="Create: SO_NOSIGPIPE" rel="nofollow" href="http://www.wlug.org.nz/SO_NOSIGPIPE?action=create">?</a></span>. 对于服务器端,我们可以使用这个标志。目的是不让其发送SIG_PIPE信号,导致程序退出。</p>
<p class="tightenable bottom">如果flags为0,则和read,write一样的操作.还有其它的几个选项,不过我们实际上用的很少,可以查看 Linux Programmer's Manual得到详细解释.</p>
</div>
</div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值