新人求救:多线程socket问题!

gsrhhy 2013-02-04 10:39:48
最近希望用多线程方法写一个proxy的小软件,可是程序总是下载数据不全,要不就是连接服务器错误,怎么办?先谢谢大家了!

代码贴上:
#include "process.h"
#include "string.h"
#include "winsock2.h"
#include "stdio.h"
#include <iostream>
#include "windows.h"

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

class http_head{
public:
char method[10];
char host[50];
char ip[16];
unsigned is_connect;
unsigned port;

http_head()
{
memset(method,0,sizeof(method));
memset(host,0,sizeof(host));
memset(ip,0,sizeof(ip));
is_connect=1;
port=80;
}
};

class sck{
public:
DWORD id_local;
DWORD id_remote;
SOCKET sck_local;
SOCKET sck_remote;
HANDLE hde_remote;
HANDLE hde_local;
unsigned exit;
unsigned change;

sck()
{
exit=0;
change=0;
}
};

int n_thread=0;

void DnsLookup(char *host,char *ip)
{
PHOSTENT phoStent;

if((phoStent=gethostbyname(host))==NULL)
{
std::cout<<"\ndns lookup error!\n"<<std::endl;
sprintf(ip,"0.0.0.0");
}
else
{
sprintf(ip,"%s",inet_ntoa(*((struct in_addr*)phoStent->h_addr_list[0])));
}
return;
}

http_head convert(char *szHead)
{
int i_tmp,j_tmp;
http_head head;
char *c_tmp;
char szHeadc[65536];

i_tmp = strchr(&szHead[0], ' ') - &szHead[0];
strncpy(&(head.method)[0], &szHead[0], i_tmp);
head.method[i_tmp] = '\0';

if(strstr(&(head.method[0]),"GET"))
{
i_tmp=strstr(&szHead[0], "://")-&szHead[0]+3;
j_tmp=strchr(&szHead[i_tmp],'/')-&szHead[i_tmp];
strncpy(&(head.host[0]),&szHead[i_tmp],j_tmp);
head.host[j_tmp]='\0';
if((c_tmp=strchr(&(head.host[0]), ':'))!=NULL)
{
head.port=atoi(c_tmp);
head.host[c_tmp-&(head.host[0])]='\0';
}
else head.port=80;

j_tmp = 4;
c_tmp = strtok(&szHead[0], "\n");
c_tmp = strstr(c_tmp, "://") + 3;
c_tmp = strstr(c_tmp, "/");
szHeadc[0] = 'G';szHeadc[1] = 'E';szHeadc[2] = 'T' ;szHeadc[3] = ' ';
i_tmp = strlen(c_tmp);
strncpy(&szHeadc[j_tmp], c_tmp, i_tmp);
j_tmp += i_tmp;
szHeadc[j_tmp++] = '\n';
while(1)
{
c_tmp = strtok(NULL, "\n");
if(c_tmp==NULL) break;
if((*(c_tmp+1)=='r')&&(*(c_tmp+2)=='o')&&(*(c_tmp+3)=='x')&&(*(c_tmp+4)=='y'))
{
if((strstr(c_tmp, "lose")-c_tmp)>2)
{
szHeadc[j_tmp] = '\0';
strcat(szHeadc,"Connection:Close\n");
j_tmp += 17;
head.is_connect = 0;
}
else
{
szHeadc[j_tmp] = '\0';
strcat(szHeadc, "Connection:Keep-Alive\n");
j_tmp += 22;
}
}
else
{
i_tmp = strlen(c_tmp);
strncpy(&szHeadc[j_tmp], c_tmp, i_tmp);
j_tmp += i_tmp;
szHeadc[j_tmp++] = '\n';
}
}
szHeadc[j_tmp] = '\0';
strncpy(szHead, szHeadc, j_tmp);
}
else if(strstr(&(head.method[0]),"CONNECT"))
{
i_tmp=strchr(&szHead[0],' ')-&szHead[0]+1;
j_tmp=strchr(&szHead[i_tmp],' ')-&szHead[i_tmp];
strncpy(&(head.host[0]), &szHead[i_tmp], j_tmp);
head.host[j_tmp]='\0';
c_tmp=strchr(&(head.host[0]),':');
head.port=atoi(c_tmp);
head.host[c_tmp-&(head.host[0])]='\0';
head.is_connect=1;
}
DnsLookup(head.host,head.ip);
return head;
}

void sev_remote(LPVOID lpParameter)
{
SOCKET sck_local = ((sck*)lpParameter)->sck_local;
SOCKET sck_remote = ((sck*)lpParameter)->sck_remote;
HANDLE hde_local = ((sck*)lpParameter)->hde_local;
DWORD id_local = ((sck*)lpParameter)->id_local;
char szData[65536]="";
int size;

while(1)
{
if(((sck*)lpParameter)->exit==1)
{
closesocket(sck_local);
closesocket(sck_remote);
delete (sck*)lpParameter;
ExitThread(0);
}
size=recv(sck_remote, szData, 65536,0);
if(size==SOCKET_ERROR){Sleep(1);continue;}
if((size==0)&&(((sck*)lpParameter)->change==0)) {printf("%d--Remote host closed!\n",((sck*)lpParameter)->id_remote);((sck*)lpParameter)->exit=1;ExitThread(0);}
send(sck_local,szData,size,0);
}
}

void sev_local(LPVOID* lpParameter)
{
SOCKET sck_local = ((sck*)lpParameter)->sck_local;
SOCKET sck_remote = ((sck*)lpParameter)->sck_remote;
HANDLE hde_remote = ((sck*)lpParameter)->hde_remote;
DWORD id_remote = ((sck*)lpParameter)->id_remote;
char szHead[65536]="";
int size;
int nNetTimeout=1000;
sockaddr_in addr_remote;
addr_remote.sin_addr.S_un.S_addr=inet_addr("0.0.0.0");
http_head head;

while(1)
{
if(((sck*)lpParameter)->exit==1)
{
closesocket(sck_local);
closesocket(sck_remote);
delete (sck*)lpParameter;
ExitThread(0);
}

size=recv(sck_local, szHead, 65536,0);
if(size==SOCKET_ERROR) {Sleep(1);continue;}
if(size==0) {printf("Receive local port closed!\n"); ((sck*)lpParameter)->exit=1;ExitThread(0);}
head = convert(szHead);
// printf("%s",szHead);

printf("%d--Connecting to:%s\n",id_remote,head.host);

if(addr_remote.sin_addr.S_un.S_addr!=inet_addr(head.ip))
{
((sck*)lpParameter)->change=1;
addr_remote.sin_family=AF_INET;
addr_remote.sin_port=htons(head.port);
addr_remote.sin_addr.S_un.S_addr=inet_addr(head.ip);
closesocket(sck_remote);
sck_remote=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
setsockopt(sck_remote, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
setsockopt(sck_remote, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
if(connect(sck_remote,(sockaddr*)&addr_remote,sizeof(addr_remote))==SOCKET_ERROR){printf("%d:Connect Error:%s\n",WSAGetLastError(),head.host); ((sck*)lpParameter)->exit=1;ExitThread(0);}
((sck*)lpParameter)->change=0;
}
if(send(sck_remote,szHead,size,0)==SOCKET_ERROR){printf("%s:Sending head error:%s\n",WSAGetLastError(),head.host); ((sck*)lpParameter)->exit=1;ExitThread(0);}
}
}

int main()
{
WSADATA wsaData;
int iRet = WSAStartup(MAKEWORD(1,1), &wsaData);
if(iRet!=0) {std::cout<<"cannot start wsa!"; return -1;}

if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1)
{
std::cout<<"wsa error!";
WSACleanup();
return -1;
}

SOCKET m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8089);
if(bind(m_socket, (SOCKADDR*)&addrSrv,sizeof(SOCKADDR))==SOCKET_ERROR)
{
std::cout<<"bind error!";
closesocket(m_socket);
return -1;
}
if (listen(m_socket,10)==SOCKET_ERROR)
{
std::cout<<"listen error!";
closesocket(m_socket);
return -1;
}

std::cout<<"Listening on port 8089......."<<std::endl;

DWORD dwThreadid_local,dwThreadid_remote;
HANDLE hThread_local,hThread_remote;

SOCKET sck_local,sck_remote;
SOCKADDR_IN addrClient;
int nNetTimeout=1000;
sck *SOCKETS;
int len=sizeof(SOCKADDR);

while(1)
{
sck_local = SOCKET_ERROR;
while(sck_local==SOCKET_ERROR)
{
sck_local = accept(m_socket, (SOCKADDR*)&addrClient, &len);
}

SOCKETS=new sck;
sck_remote = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
setsockopt(sck_local, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout, sizeof(int));
setsockopt(sck_local, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout, sizeof(int));
setsockopt(sck_remote, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
setsockopt(sck_remote, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
SOCKETS->sck_local = sck_local;
SOCKETS->sck_remote = sck_remote;
SOCKETS->hde_remote = 0;
SOCKETS->hde_local = 0;

hThread_remote = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sev_remote, (LPVOID*)SOCKETS, CREATE_SUSPENDED, &dwThreadid_remote);
SOCKETS->hde_remote = hThread_remote;
SOCKETS->id_remote = dwThreadid_remote;
hThread_local = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sev_local, (LPVOID*)SOCKETS, CREATE_SUSPENDED, &dwThreadid_local);
SOCKETS->hde_local=hThread_local;
SOCKETS->id_local = dwThreadid_local;
ResumeThread(hThread_remote);ResumeThread(hThread_local);
}
return 0;
}
...全文
191 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
shiter 2013-02-16
  • 打赏
  • 举报
回复
关注一下,太长看不懂
gsrhhy 2013-02-04
  • 打赏
  • 举报
回复
引用 3 楼 yang79tao 的回复:
你用我的st_asio_wrapper试试,代码比你这个简单多了。 看我的博客。
谢谢学习了,我更想了解我的代码有什么致命的问题。
youngwolf 2013-02-04
  • 打赏
  • 举报
回复
你用我的st_asio_wrapper试试,代码比你这个简单多了。 看我的博客。
gsrhhy 2013-02-04
  • 打赏
  • 举报
回复
我是这样设计的,尽管很简陋:简单的将浏览器的数据发送到远程服务器,再接收数据发回浏览器,只是一个转发的作用,不过我认为问题可能出在对recv和send返回值的处理上?
zhangyihu321 2013-02-04
  • 打赏
  • 举报
回复
很好 发现问题是解决问题的第一步 。。。,数据下不全是由于你没有指定相关的协议重发数据,服务器断开连接应开需要重连机制来保证啊。。。
YunXia98Li 2013-02-04
  • 打赏
  • 举报
回复
看看这里的socket例子吧: http://download.csdn.net/detail/geoff08zhang/4571358

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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