各位高手能否帮忙解决一下下面这个程序的问题,while循环时为和会出现服务器无限重发最后一包数据。谢谢了!
#include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>
#include <signal.h>
#include <iostream.h>
#include <Windows.h>
#include <io.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
int main(int argc, char* argv[])
{
struct sockaddr_in address,address1;
int i,j,s,s1,tn[4]={0};
int err;
int new_s,n1;
int n=0;
int ret;
struct timeval t2;
char buf[1000],buftem[1000];
int optLen = sizeof(int);
fd_set r, w, e;
WORD wVer;
WSADATA wsaData;
wVer=MAKEWORD(1,1);
err=WSAStartup(wVer,&wsaData);//判断Windows sockets dll版本,初始化
if(err!=0)
return(0); s = socket (AF_INET, SOCK_STREAM, 0);//创建socket
if (s == -1)
{j=WSAGetLastError();
return -1;
}
i = 1;
address.sin_family = AF_INET;
address.sin_port = htons (8000);//监听端口8000 address.sin_addr.s_addr = INADDR_ANY;
if (bind (s, (struct sockaddr *)&address, sizeof (address)) == -1)
{
return -1;
} if (listen (s, 1) == -1)//监听,设置监听队列为1,为了简化程序
{
return -1;
}
printf("正在等待请求,请稍后\n");
new_s=accept(s,NULL,NULL);//accept客户端连接,new_s是用于代理和客户端的连接
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建新连接,用于连接http服务器
address.sin_family=AF_INET;
address.sin_addr.s_addr = inet_addr( "127.0.0.1" );
address.sin_port = htons( 80 );
if (ConnectSocket!=INVALID_SOCKET)
{
printf("socket创建\n"); int nn=connect( ConnectSocket, (SOCKADDR*) &address, sizeof(address) );}//进行连接
while(1)//循环处理
{
FD_ZERO (&r);
FD_ZERO (&w);
FD_ZERO (&e);
FD_SET(new_s,&r);
FD_SET(new_s,&w);
FD_SET(new_s,&e);
FD_SET(ConnectSocket,&r);
FD_SET(ConnectSocket,&w);
FD_SET(ConnectSocket,&e);
//t2.tv_sec=5;
//t2.tv_usec=5*1000;
ret=select(new_s+1,&r,&w,&e,NULL);//查看socket状态
if(FD_ISSET(new_s,&r))//如果客户端发送数据包,则接收并转发服务器端
{
n = recv(new_s, buf, strlen(buf),0);
if(n!=-1)
{
tn[0]++;
printf("这是从客户端收到的第%d包,内容是:%s,\n报文长度:%d.\n",tn[0],buf,n);//打印相关信息用于调试
n1=send(ConnectSocket,buf,n,0);
if(n1!=-1)
{
tn[1]++;
printf("向服务器端转发报文数%d,转发报文长度%d\n",tn[1],n1);
}
}
}
if(FD_ISSET(ConnectSocket,&r))//如果服务器端发送数据包,接收并转发客户端
{ n1=recv(ConnectSocket,buftem,strlen(buftem),0);//出问题的地方,最后一包时
if(n1!=-1)
{
tn[2]++;
printf("这是从服务器端收到的第%d包,内容是:%s,报文长度是:%d.\n",tn[2],buftem,n1);
if(FD_ISSET(new_s,&w))
//strcat(buftem,"#13#10");
{n = send(new_s, buftem,n1,0);
if(n!=-1)
{
tn[3]++;
printf("向客户端转发报文数%d,转发报文长度%d.\n",tn[3],n);
//if(tn[3]==50)///////////此处因为程序会无限循环发报,所以设置一最大发包数控制程序////////////////
//{break;}
}
}
//Sleep(200);
}
}
}
}
这个程序可以在vc下直接执行。谢谢!另如何让连接keep alive?
#include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>
#include <signal.h>
#include <iostream.h>
#include <Windows.h>
#include <io.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
int main(int argc, char* argv[])
{
struct sockaddr_in address,address1;
int i,j,s,s1,tn[4]={0};
int err;
int new_s,n1;
int n=0;
int ret;
struct timeval t2;
char buf[1000],buftem[1000];
int optLen = sizeof(int);
fd_set r, w, e;
WORD wVer;
WSADATA wsaData;
wVer=MAKEWORD(1,1);
err=WSAStartup(wVer,&wsaData);//判断Windows sockets dll版本,初始化
if(err!=0)
return(0); s = socket (AF_INET, SOCK_STREAM, 0);//创建socket
if (s == -1)
{j=WSAGetLastError();
return -1;
}
i = 1;
address.sin_family = AF_INET;
address.sin_port = htons (8000);//监听端口8000 address.sin_addr.s_addr = INADDR_ANY;
if (bind (s, (struct sockaddr *)&address, sizeof (address)) == -1)
{
return -1;
} if (listen (s, 1) == -1)//监听,设置监听队列为1,为了简化程序
{
return -1;
}
printf("正在等待请求,请稍后\n");
new_s=accept(s,NULL,NULL);//accept客户端连接,new_s是用于代理和客户端的连接
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//创建新连接,用于连接http服务器
address.sin_family=AF_INET;
address.sin_addr.s_addr = inet_addr( "127.0.0.1" );
address.sin_port = htons( 80 );
if (ConnectSocket!=INVALID_SOCKET)
{
printf("socket创建\n"); int nn=connect( ConnectSocket, (SOCKADDR*) &address, sizeof(address) );}//进行连接
while(1)//循环处理
{
FD_ZERO (&r);
FD_ZERO (&w);
FD_ZERO (&e);
FD_SET(new_s,&r);
FD_SET(new_s,&w);
FD_SET(new_s,&e);
FD_SET(ConnectSocket,&r);
FD_SET(ConnectSocket,&w);
FD_SET(ConnectSocket,&e);
//t2.tv_sec=5;
//t2.tv_usec=5*1000;
ret=select(new_s+1,&r,&w,&e,NULL);//查看socket状态
if(FD_ISSET(new_s,&r))//如果客户端发送数据包,则接收并转发服务器端
{
n = recv(new_s, buf, strlen(buf),0);
if(n!=-1)
{
tn[0]++;
printf("这是从客户端收到的第%d包,内容是:%s,\n报文长度:%d.\n",tn[0],buf,n);//打印相关信息用于调试
n1=send(ConnectSocket,buf,n,0);
if(n1!=-1)
{
tn[1]++;
printf("向服务器端转发报文数%d,转发报文长度%d\n",tn[1],n1);
}
}
}
if(FD_ISSET(ConnectSocket,&r))//如果服务器端发送数据包,接收并转发客户端
{ n1=recv(ConnectSocket,buftem,strlen(buftem),0);//出问题的地方,最后一包时
if(n1!=-1)
{
tn[2]++;
printf("这是从服务器端收到的第%d包,内容是:%s,报文长度是:%d.\n",tn[2],buftem,n1);
if(FD_ISSET(new_s,&w))
//strcat(buftem,"#13#10");
{n = send(new_s, buftem,n1,0);
if(n!=-1)
{
tn[3]++;
printf("向客户端转发报文数%d,转发报文长度%d.\n",tn[3],n);
//if(tn[3]==50)///////////此处因为程序会无限循环发报,所以设置一最大发包数控制程序////////////////
//{break;}
}
}
//Sleep(200);
}
}
}
}
这个程序可以在vc下直接执行。谢谢!另如何让连接keep alive?
{}
条件永远成立,++到最后一个包上,当然无休止的循环发送最后的一包数据了,只要在while循环中加个if语句,判断一下是不是最后一包,如果是最后一包的话,把最后一包发完后跳出来就可以了
下面摘自MSDN。
If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
to guxingfeiyu:调试时我用过memset(buf, 0, sizeof(buf));
n = recv(new_s, buf, sizeof(buf),0);仍是同样的问题这是为什么?并且程序在实际运行时,当服务器发完最后一包后,此时调用select监测与服务器连接的socket状态仍为可读,而此时调用recv()接收仍为最后一包数据,返回成功接收的字节数(不是0),这就是造成无限循环发最后一包的错误所在,但不知如何解决,所以请各位高手帮忙解决一下,谢谢!谢谢各位向我提供了解决问题的方法、提议;