单个接收没有问题,两个接收过来不崩溃了,数据开始还是好的,一会就乱了,有的也没有接收完。server:
#include<stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <string.h>#pragma comment(lib,"ws2_32.lib")#define PORT 9999
#define IPADDR "127.0.0.1"
#define BACKLOG 20
#define FILENAME 200
#define LENGTH 200
#define BUFFERSIZE 1024*8struct FILEHEAD //FILE-head struct
{
char filename[LENGTH];//file name
unsigned int length;//the byte of the file};struct FILEDATA //FILE-data struct
{
char filename[LENGTH];//file name
char package[BUFFERSIZE];//package data
unsigned int length;//the byte of the file
unsigned int index;//index of the package};struct sockaddr_in clientaddr; //Definition of the external variable for thread function callvoid getFileInformation(FILEHEAD file)
{
printf( "file information :\n" );
printf( " Filename: %s\n", file.filename );
//printf( " Ext: %s\n", file.ext );
printf( " the file length is: %ld btye\n", file.length );
}void showClientinfo()
{
//获取当前系统时间
SYSTEMTIME st;
GetLocalTime(&st);
char SysDate[30];
//将systime中的时间转变为字符串存入SysDate[30];
sprintf(SysDate, "%4d-%2d-%2d %2d:%2d:%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
//Server显示客户端信息
printf("%s Recv from Client [%s:%d] : %s\n", SysDate, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
//服务器向客户端回显信息
}DWORD WINAPI requestThread(LPVOID lparam)
{
FILEHEAD filehead;
FILEDATA filedata;
SOCKET newsock=(SOCKET)(LPVOID)lparam;
//char buf[BUFFERSIZE]={0};
memset(&filehead,0,sizeof(filehead));
memset(&filedata,0,sizeof(filedata)); showClientinfo(); //printf("等待文件头信息 ...\n"); int length_file_info=recv(newsock,(char *)&filehead,sizeof(filehead),0);
if (SOCKET_ERROR==length_file_info)
{
printf("receive failed!\n");
closesocket(newsock);
return -1;
}
if (length_file_info<=0)
{
exit(1);//异常退出
} getFileInformation(filehead);//打印文件信息 FILE *fp=NULL;
fp=fopen(filehead.filename,"wb+");
if (NULL==fp)
{
perror("fail to build the file!!!\n");
exit(1);
}
//printf("要接收的文件名为:");
//printf(filehead.filename);//打印文件名
//printf ("\n catch file now....\n");
int recv_length=0;//接收到字节的长度
//Sleep(100);
printf("开始接收...\n");
filedata.index=0;
while (1)
{
recv_length=recv(newsock,(char *)&filedata,sizeof(filedata),0);
if (recv_length == SOCKET_ERROR)
{
printf("recv failed !\n");
closesocket(newsock);
//WSACleanup();
return -1;
}
fwrite(filedata.package,1,BUFFERSIZE,fp);
if (0==recv_length)
{
break;
}
//printf("第%d块接收成功!\n",filedata.index);
}
printf("\n接收完成...\n\n");
fflush(fp);
fclose(fp);
fp=NULL;
return 0;
}int main(int argc,char *argv[])
{
//初始化winsock版本信息,加载动态链接库(dll)
WSADATA wsData;
if (WSAStartup(MAKEWORD(2,2),&wsData)!=0)
{
printf("WSAStartup failed !!!\n");
return -1;
}
//创建套接字
SOCKET socklisten;
if((socklisten=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
{
printf("socket failed!!!\n");
WSACleanup();
return -1;
}
//设置服务器地址
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(PORT);
servaddr.sin_addr.S_un.S_addr=inet_addr(IPADDR);
//绑定socket地址结构到监听套接字
if (bind(socklisten,(sockaddr *)&servaddr,sizeof(servaddr))!=0)
{
printf("binding failed!!!\n");
closesocket(socklisten);
WSACleanup();
}
//在server上运行监听
if (listen(socklisten,20)!=0)
{
printf("listen failed !!!\n");
closesocket(socklisten);
WSACleanup();
return -1;
}
//接收客户端的连接请求
printf("TCP server is start!!!\n");
//clientaddrlength要有初值,
int client_addr_length = sizeof(clientaddr);
memset(&clientaddr,0,client_addr_length);
SOCKET connect;
//循环等待
while (1)
{
if ((connect=accept(socklisten,(sockaddr *)&clientaddr,&client_addr_length))==INVALID_SOCKET)
{
printf("accept failed!!!\n");
closesocket(connect);
WSACleanup();
return -1;
}
//创建新线程
DWORD ThreadID;
CreateThread(NULL,0,requestThread,(LPVOID)connect,0,&ThreadID);
}
}
#include<stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <string.h>#pragma comment(lib,"ws2_32.lib")#define PORT 9999
#define IPADDR "127.0.0.1"
#define BACKLOG 20
#define FILENAME 200
#define LENGTH 200
#define BUFFERSIZE 1024*8struct FILEHEAD //FILE-head struct
{
char filename[LENGTH];//file name
unsigned int length;//the byte of the file};struct FILEDATA //FILE-data struct
{
char filename[LENGTH];//file name
char package[BUFFERSIZE];//package data
unsigned int length;//the byte of the file
unsigned int index;//index of the package};struct sockaddr_in clientaddr; //Definition of the external variable for thread function callvoid getFileInformation(FILEHEAD file)
{
printf( "file information :\n" );
printf( " Filename: %s\n", file.filename );
//printf( " Ext: %s\n", file.ext );
printf( " the file length is: %ld btye\n", file.length );
}void showClientinfo()
{
//获取当前系统时间
SYSTEMTIME st;
GetLocalTime(&st);
char SysDate[30];
//将systime中的时间转变为字符串存入SysDate[30];
sprintf(SysDate, "%4d-%2d-%2d %2d:%2d:%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
//Server显示客户端信息
printf("%s Recv from Client [%s:%d] : %s\n", SysDate, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
//服务器向客户端回显信息
}DWORD WINAPI requestThread(LPVOID lparam)
{
FILEHEAD filehead;
FILEDATA filedata;
SOCKET newsock=(SOCKET)(LPVOID)lparam;
//char buf[BUFFERSIZE]={0};
memset(&filehead,0,sizeof(filehead));
memset(&filedata,0,sizeof(filedata)); showClientinfo(); //printf("等待文件头信息 ...\n"); int length_file_info=recv(newsock,(char *)&filehead,sizeof(filehead),0);
if (SOCKET_ERROR==length_file_info)
{
printf("receive failed!\n");
closesocket(newsock);
return -1;
}
if (length_file_info<=0)
{
exit(1);//异常退出
} getFileInformation(filehead);//打印文件信息 FILE *fp=NULL;
fp=fopen(filehead.filename,"wb+");
if (NULL==fp)
{
perror("fail to build the file!!!\n");
exit(1);
}
//printf("要接收的文件名为:");
//printf(filehead.filename);//打印文件名
//printf ("\n catch file now....\n");
int recv_length=0;//接收到字节的长度
//Sleep(100);
printf("开始接收...\n");
filedata.index=0;
while (1)
{
recv_length=recv(newsock,(char *)&filedata,sizeof(filedata),0);
if (recv_length == SOCKET_ERROR)
{
printf("recv failed !\n");
closesocket(newsock);
//WSACleanup();
return -1;
}
fwrite(filedata.package,1,BUFFERSIZE,fp);
if (0==recv_length)
{
break;
}
//printf("第%d块接收成功!\n",filedata.index);
}
printf("\n接收完成...\n\n");
fflush(fp);
fclose(fp);
fp=NULL;
return 0;
}int main(int argc,char *argv[])
{
//初始化winsock版本信息,加载动态链接库(dll)
WSADATA wsData;
if (WSAStartup(MAKEWORD(2,2),&wsData)!=0)
{
printf("WSAStartup failed !!!\n");
return -1;
}
//创建套接字
SOCKET socklisten;
if((socklisten=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
{
printf("socket failed!!!\n");
WSACleanup();
return -1;
}
//设置服务器地址
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(PORT);
servaddr.sin_addr.S_un.S_addr=inet_addr(IPADDR);
//绑定socket地址结构到监听套接字
if (bind(socklisten,(sockaddr *)&servaddr,sizeof(servaddr))!=0)
{
printf("binding failed!!!\n");
closesocket(socklisten);
WSACleanup();
}
//在server上运行监听
if (listen(socklisten,20)!=0)
{
printf("listen failed !!!\n");
closesocket(socklisten);
WSACleanup();
return -1;
}
//接收客户端的连接请求
printf("TCP server is start!!!\n");
//clientaddrlength要有初值,
int client_addr_length = sizeof(clientaddr);
memset(&clientaddr,0,client_addr_length);
SOCKET connect;
//循环等待
while (1)
{
if ((connect=accept(socklisten,(sockaddr *)&clientaddr,&client_addr_length))==INVALID_SOCKET)
{
printf("accept failed!!!\n");
closesocket(connect);
WSACleanup();
return -1;
}
//创建新线程
DWORD ThreadID;
CreateThread(NULL,0,requestThread,(LPVOID)connect,0,&ThreadID);
}
}
解决方案 »
- 确认及寻求解决办法 非管理员用户是否不能使用CREATFILE开启\\.\physicaldriver1类似的U盘?
- 如果recv()第三个参数指定为0来测试对方是否异常关闭,有无后果?
- 如何导出vista下windows mail 的联系人
- LINK : fatal error LNK1104: cannot open file "?.exe"
- 怎样用ClassWizard添加Function?
- 求教简单多线程问题
- 怎样捕获回车键消息
- 我选择一个dialog(对话框),怎么在操作完成后把整合后的数据写到光标处,我在详细讲下
- 如何做一个批处理文件呀?
- 为何编译通过,运行中老是出错。多串口通讯。
- tcp多线程服务器,接收数据乱的。求指导
- MFC单文档视图应该程序不能接收到另一个进程发来的WM_COPYDATA消息。
while (1)
{
if ((connect=accept(socklisten,(sockaddr *)&clientaddr,&client_addr_length))==INVALID_SOCKET)
{
printf("accept failed!!!\n");
closesocket(connect);
WSACleanup();
return -1;
}
//创建新线程
DWORD ThreadID;
CreateThread(NULL,0,requestThread,(LPVOID)connect,0,&ThreadID);
}
你这个循环创建线程的条件不应该是1 !
一个socket应该有一个独立线程来处理
不同的socket之间不会出现串扰啊
Socket的Send,Recv的长度问题:
一个包没有固定长度,以太网限制在46-1500字节,1500就是以太网的MTU,超过这个量,TCP会为IP数据报设置偏移量进行分片传输,现在一般可允许应用层设置8k(NTFS系统)的缓冲区,8k的数据由底层分片,而应用层看来只是一次发送。
if (SOCKET_ERROR==length_file_info)
{
printf("receive failed!\n");
closesocket(newsock);
return -1;
}
if (length_file_info<=0)
{
exit(1);//异常退出
}
getFileInformation(filehead);//打印文件信息
代码没有仔细看,一眼看到这个地方,肯定就有问题了。tcp是流协议,你这边一次recv得到的不一定是一个sizeof(filehead)长度的数据,来供你解析这个结构体,因此你后续数据可能就会错乱了。你自己仔细看看,永远记住tcp是流,不是一个个包的概念,send一次什么,recv一次并不一定就得到send的完整数据
http://blog.csdn.net/jwybobo2007/article/details/6164362