我写了一个C/S的测试程序,服务器端如下:
#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")DWORD WINAPI ServerThread(LPVOID pParam)
{
SOCKET server, client;
WSADATA wsaData;
sockaddr_in local, from;
int fromlen = sizeof (from);
char buf[78]; printf ("Starting up TCP server\r\n"); WSAStartup(0x101,&wsaData);
local.sin_family=AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons(40000); server=socket(AF_INET,SOCK_STREAM,0);
bind(server,(sockaddr*)&local,sizeof(local));
listen(server,5); client=accept(server, (struct sockaddr*)&from,&fromlen);
printf ("connect from %s\n", inet_ntoa(from.sin_addr));
while (true) {
memset (buf, 0, 78);
if (recv (client, buf, 78, 0)< 0) break;  // maybe closed by peer
send(client, buf, 78, 0);
}
closesocket(client);
closesocket(server);
WSACleanup();
printf ("socket closed.\n");
return 0;
}int main(int argc, char* argv[])
{
DWORD id;
CreateThread (NULL, 0, ServerThread, 0, 0, &id);
getchar ();
return 0;
}
============================
客户端代码:
#include "stdafx.h"
#include   <stdio.h>  
#include   <stdlib.h>  
#include   <winsock2.h>  
#pragma comment(lib, "ws2_32.lib")int main(int argc, char *argv[])  
{
SOCKET sClient;  
    struct sockaddr_in server;
char buf[78];
WSADATA wsaData;
DWORD dwStart, dwStop;
WSAStartup(0x101,&wsaData);
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
server.sin_family = AF_INET;
server.sin_port = htons(40000);  
server.sin_addr.s_addr = inet_addr("192.168.1.30");  
if(connect(sClient, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("connect() failed: %d\n", WSAGetLastError());  
return 0;
}  
while (true) {
for (int i = 0; i < 78; i++) buf[i] = i;
dwStart = GetTickCount ();
send (sClient, buf, 78, 0);
if (recv (sClient, buf, 78, 0)< 0) {
printf ("socket closed.\n"); 
getchar ();
break;
}
dwStop = GetTickCount ();
printf ("%d ms\n", dwStop-dwStart);
if ((dwStop-dwStart) >= 10) {
FILE *fp;
fp = fopen ("c:\\time2.txt", "at");
fprintf (fp, "%d ms\n", dwStop-dwStart);
fclose (fp);
}
Sleep (1000);
}
closesocket(sClient);  
WSACleanup();  
return 0;  
}
===========================
临时写的测试程序,少了一些出错判断,大侠们别见怪,呵呵
服务器端是一个echo服务,把收到的报文发回去。
客户端每隔1秒向服务端发送一个78字节的报文,检测报文来回的时间,如果大于10ms就记录在文件里,同时在客户端用sniffer抓包。
问题是:
客户端不定期有10-20ms的时延,有时长达90ms,虽然比较少,但晚上开了几个小时就有20多个报文被延时,从抓包情况来看,每个报文都在0.5ms左右就返回了,没有延时现象,表明服务端返回的数据在0.5ms左右就已经到达了客户端的协议栈,但客户端程序表现出来的现象,好像应用层在读取socket时被延时了,我修改了客户端程序,确实在出问题的时候recv阻塞了一段时间(这个时候sniffer已经抓到了完整的返回的报文),也就是说,从sniffer抓到返回报文直到recv收到数据,这个中间有时会延时,最长能达到90ms,既然sniffer已经抓到返回报文,那么应该和网络状况没有什么关系了,但,这个延时是怎么回事呢?
采用select等待数据,结果一样。
曾怀疑是时间片的问题,开机后什么程序也没开,客户端程序优先级调到realtime,没有明显的改善。
因为在项目中我们写了一个通讯的dll,延时现象更为严重,因此就写了测试程序来测试,结果也发现有延时现象,困扰几天了,一直想不明白是怎么回事,望哪位大侠能指点迷津,非常感谢!

解决方案 »

  1.   

    要测试socket性能,需要对socket进行一下设置
    setsocketopt
    read、write buffer
    是否粘包等
      

  2.   

    socket编程的精华就在setsockopt、ioctlsocket等控制函数上
      

  3.   

    SO_RCVBUF
    SO_SNDBUF
    TCP_NODELAY
      

  4.   

    谢谢指点!
    我仔细看了setsockopt的选项,好像没这么简单哦,跟这个问题相关的SOL_SOCKET选项基本上只有SO_RCVBUF和SO_RCVLOWAT(设为1),这两个我都试了一下,还有TCP_NODELAY,设了也没什么改善。还可能有哪方面的问题呢?
      

  5.   

    效率不会那么低。
    把buf设大一点,如buf[100]
    另外,发送buffer和接收buffer不要弄成同一个,在发送和接收之前memset为0
      

  6.   

    网络环境?! TCP保证是数据连续性,当丢包发生后就是要求重发。 窗口大小,重发延时可能是问题所有,也可能是你的网络环境有干扰
      

  7.   

    把buf改为buf[100],每次使用memset(buf,'\0',sizeof(buf)),还有一点,你每次实际发送的数据要小于你发送的字段长度,比如,send(sock,buf,sizeof(buf)+1,0),这样试试看,