传输连续空格导致socket网络延时

xinhua0910 2014-06-20 07:11:09

最近测试,发现交易有时成功有时超时,这两天查询总结发现现状如下:
客户端:在异地,通过专线连到我方服务器(双方不同网段)
客户端系统:XP
服务端系统:linux
现状:
1. 只要客户端发的字符串中连续空格过多时,服务器端recv接收信息时就要好几秒(是通过recv后的时间减去accept后的时间得出消耗的时间。发连续40个空格时不到1秒,80个空格时要8秒,200多空格时要几十秒);
2. 如果发的不是连续空格,哪怕是几千个字节也是秒收秒回一秒内搞定;
3. 如果在内网同网段收发,哪怕多少个空格也是一秒内搞定,不会超时。

现在怀疑是不是网络设置哪里有问题,又或者是网络设备问题,但网络工作人员也没查到什么异常。不知各位有没有碰到类似情况,麻烦各位了

(由于担心是应用系统的问题,我是单独写了很简单的socket客户端和服务器端来测试,因此不会涉及系统应用逻辑问题。)

测试服务端日志情况:
第一笔70个长度,中间4个空格,秒杀
第二笔101个长度,中间有40个空格,秒杀
第三笔141个长度,中间有80个空格,接收信息就用时8秒
/usr/xxx/tmp 1259> ./a.out
socket created .
socked id: 3
connected.
local port:3995
listening...
Fri Jun 20 15:59:30 2014
[7096]accept a new connection:4[162.61.12.29]
Fri Jun 20 15:59:30 2014
[7098]收到消息: [70][0001AINQ0222000100000000000000000000000O0619161641000028021 1]
send OK
goto END

Fri Jun 20 16:00:57 2014
[7096]accept a new connection:4[162.61.12.29]
Fri Jun 20 16:00:57 2014
[7102]收到消息: [101][0001AINQ0222000100000000000000000000000O0619161641000028021 40]
send OK
goto END

Fri Jun 20 16:01:43 2014
[7096]accept a new connection:4[162.61.12.29]
Fri Jun 20 16:01:51 2014
[7105]收到消息: [141][0001AINQ0222000100000000000000000000000O0619161641000028021 80]
send OK
goto END

socket客户端(XP下的VC程序)如下:
#include <stdio.h>
#include<WINSOCK2.H>

#pragma comment(lib,"ws2_32.lib")

#define PORT 3995
#define REMOTE_IP "163.1.8.128"

int main(int argc,char *argv[])
{
int s ,iRcv=0;
struct sockaddr_in addr ;
char mybuffer[1024];

WSADATA wsaData = {0};
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("WSAStartup failed.\n");
exit(-1);
}


if( (s=socket(AF_INET,SOCK_STREAM,0))<0 ) /*建立一个socket。*/
{
perror("socket");
printf("socket err [%d][%d]\n", s, WSAGetLastError());
exit(1);
}
else
{
printf("socket created .\n");
printf("socked id: %d \n",s);
}
memset(&addr, 0, sizeof(addr)); /*设置addr的信息。*/
addr.sin_family =AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=inet_addr(REMOTE_IP);
if(connect(s,&addr,sizeof(addr))<0) /*连接到远程服务器。*/
{
perror("connect");
printf("socket err [%d][%d]\n", s, WSAGetLastError());
close(s);
exit(1);
}
else /*输出信息。*/
{
printf("connected ok!\n");
printf("remote ip:%s\n",REMOTE_IP);
printf("remote port:%d\n",PORT);
}


strcpy(mybuffer, "0001AINQ0222000100000000000000000000000O0619161641000028021 030000005000100000000000021000000 62135600104000018008113EA0");

if(-1 == send(s, mybuffer, strlen(mybuffer), 0))
{
printf("send err!!!\n");
close(s);
exit(-1);
}
printf("send ok \n");

if(-1 == (iRcv = recv(s, mybuffer, sizeof(mybuffer), 0)))
{
printf("recv err!!!\n");
close(s);
exit(-1);
}
else
{
printf("[%d]收到消息: [%d][%s]\n", getpid(), iRcv, mybuffer);
}

getch();
close(s);
return 0;
}


socket服务端(Linux)如下:
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <time.h>

#define IPADDR "127.0.0.1"
#define PORT 3995
#define MAX 10

int main()
{
int iSocket, iSocket2, iRet, iAddrLen;
int iRcv=0;
char szBuf[2048];
struct sockaddr_in stAddr;
const int reuse = 1;
struct tm *ptr;
time_t loctime;

signal(SIGCLD,SIG_IGN);


if((iSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket err!\n");
exit(-1);
}
else
{
printf("socket created .\n");
printf("socked id: %d \n",iSocket);
}


if(iRet = setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)))
{
printf("setsockopt err![%d][%d]\n", iRet, errno);
close(iSocket);
exit(-1);
}

memset(&stAddr, 0, sizeof(stAddr));
stAddr.sin_family =AF_INET;
stAddr.sin_port = htons(PORT);
stAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if((iRet = bind(iSocket, &stAddr, sizeof(stAddr))) < 0)
{
printf("bind err![%d][%d]\n", iRet, errno);
close(iSocket);
exit(-1);
}
else
{
printf("connected.\n");
printf("local port:%d\n",PORT) ;
}

if((iRet = listen(iSocket, 3)) < 0)
{
printf("listen err![%d]\n", iRet);
goto ERR;
}
else
{
printf("listening...\n");
}

iAddrLen = sizeof(stAddr);

while(1)
{
if((iSocket2 = accept(iSocket, &stAddr, &iAddrLen)) < 0)
{
printf("accept err![%d][%d][%s]\n", iSocket2, errno, strerror(errno));
goto ERR;
}
else
{
loctime=time(NULL);
ptr=localtime(&loctime);
printf(asctime(ptr));
printf("[%d]accept a new connection:%d[%s]\n", getpid(), iSocket2, inet_ntoa(stAddr.sin_addr));
}

if((iRet = fork()) < 0)
{
printf("fork err! \n");
goto ERR;
}
else if(iRet > 0)
{
// printf("Let Son To Recieve It,I Continue To accept\n");
close(iSocket2);
continue;
}

memset(szBuf, 0, sizeof(szBuf));
if(-1 == (iRcv = recv(iSocket2, szBuf, sizeof(szBuf), 0)))
{
printf("recv err!!![%d][%s]\n", errno, strerror(errno));
goto ERR;
}
else
{
loctime=time(NULL);
ptr=localtime(&loctime);
printf(asctime(ptr));
printf("[%d]收到消息: [%d][%s]\n", getpid(), iRcv, szBuf);
}

memset(szBuf, 0, sizeof(szBuf));
strcpy(szBuf, "快点好吧,受不了啦");
if(-1 == send(iSocket2, szBuf, strlen(szBuf), 0))
{
printf("send err!!!\n");
goto ERR;
}
else
{
printf("send OK\n");
}

goto END;
}

ERR:
close(iSocket);
close(iSocket2);
printf("server ERR\n");
return -123;
END:
close(iSocket);
close(iSocket2);
printf("goto END\n");
return 0;
}

...全文
385 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
xinhua0910 2014-08-20
  • 打赏
  • 举报
回复
谢谢两位回复,不过,都没什么价值。另外,赵老师,你的观点我知道,只是我们不是专门写传输工具的,而是特定环境的通信,所以不需要处理那么复杂。 回正题: socket通讯连接空格就导致接收耗时好几秒甚至几十秒的情况,公司网络人员也查了半个月,改过一堆的参数,都没有查出来。不过总结发现,走联通网络时没有问题,走电信网络时就延时。 后来找设备供应商一起查,也没有查到问题所在。最后,让设备商换了台“协议转换器”(好像是光纤转135什么的设备),就没有这个问题了。 至次,问题也算解决了。只是不知道问题原因
赵4老师 2014-06-23
  • 打赏
  • 举报
回复
不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊! http://bbs.csdn.net/topics/380167545
xinhua0910 2014-06-23
  • 打赏
  • 举报
回复
给自己顶一下,有没有大牛碰到,求教了
碼上道 2014-06-21
  • 打赏
  • 举报
回复
可以在服务端调试一下,看看是哪个处理耗时间。 你在父进程关闭socketid,这个我感觉是不行了,如果子进程处理快,可能没有问题,但是对于复杂网络肯定是有问题的。
xinhua0910 2014-06-20
  • 打赏
  • 举报
回复
引用 1 楼 jerry_dqh 的回复:
else if(iRet > 0) { // printf("Let Son To Recieve It,I Continue To accept\n"); close(iSocket2); continue; } 父进程不能关闭socketid吧。不然子进程如何关闭啊, 总体来看server端有些问题,空格并不是什么特殊的字符,应该没有啥区别。
server端没问题,客户端发连续几十个空格就有问题,如果不发空格,发多少就正常; 如果把客户端放内网,随便发多少空格都没有问题。唯独客户端在异地时向服务器发连续几十个空格时recv时间就长了,发非空格时上千个字节都是秒杀
碼上道 2014-06-20
  • 打赏
  • 举报
回复
else if(iRet > 0) { // printf("Let Son To Recieve It,I Continue To accept\n"); close(iSocket2); continue; } 父进程不能关闭socketid吧。不然子进程如何关闭啊, 总体来看server端有些问题,空格并不是什么特殊的字符,应该没有啥区别。

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧