C++ Socket TCP 发送文件,数据接收不全

kk216927 2017-08-22 04:58:53
把文件内容写进结构体发送到服务端,可是只能接收到文件第一行的数据
请问这是什么原因,有什么解决方法吗?

代码如下:

//client.cpp 发送new.csv文件内容

#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
#include <sstream>
#include "winsock.h"
#pragma warning(disable:4996)
#pragma comment(lib, "wsock32")
using namespace std;
struct TcsvMake
{
int bianhao;
string CELLCODE;
string IP;
string C_hao;
int EPC;
int RCS;
};

int main()
{
int ret = 0;
WSADATA wsadata;
WORD version = MAKEWORD(2, 0);
ret = WSAStartup(version, &wsadata);

SOCKET m_hClientSocket;
m_hClientSocket = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN m_addr1;
m_addr1.sin_family = AF_INET;
m_addr1.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
m_addr1.sin_port = htons(10000);
ret = connect(m_hClientSocket, (LPSOCKADDR)&m_addr1, sizeof(m_addr1));

//使用结构体转换成字符串发送,在服务器端直接转为结构体
TcsvMake msg1;
TcsvMake tcsv;
fstream input("new.csv", ios::in);
string csvLine;
// 从输入流中读取每一行
getline(input, csvLine);
while (getline(input, csvLine))
{
char *csv = (char*)csvLine.data();
if (NULL != csv)
{
string bianhao = strtok(csv, ",");
istringstream csvStream(bianhao);
csvStream >> tcsv.bianhao;

string CELLCODE = strtok(NULL, ",");
istringstream CsvStream(CELLCODE);
CsvStream >> tcsv.CELLCODE;

string ip = strtok(NULL, ",");
istringstream cSvStream(ip);
cSvStream >> tcsv.IP;

string Chao = strtok(NULL, ",");
istringstream csVStream(Chao);
csVStream >> tcsv.C_hao;

string EPC = strtok(NULL, ",");
istringstream CSvStream(EPC);
CSvStream >> tcsv.EPC;

string RCS = strtok(NULL, ",");
istringstream CSVStream(RCS);
CSVStream >> tcsv.RCS;

}

//以字符串形式发送,因为TCP/IP是字节流通信
int len_send = send(m_hClientSocket, (char *)&tcsv, sizeof(TcsvMake), 0);
}
closesocket(m_hClientSocket);
WSACleanup();
return 0;
}

...全文
1101 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
kk216927 2017-08-24
  • 打赏
  • 举报
回复
都解决啦,谢谢帮忙,结贴
赵4老师 2017-08-23
  • 打赏
  • 举报
回复
搜“序列化 反序列化” 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊! http://bbs.csdn.net/topics/380167545
kk216927 2017-08-23
  • 打赏
  • 举报
回复
问题已经解决了,谢谢各位帮忙 另外再多问一句,如果把打印出的三列数据保存到新文件中应该怎么做?
kk216927 2017-08-23
  • 打赏
  • 举报
回复
引用 4 楼 sdghchj 的回复:
[quote=引用 3 楼 zyq_0927 的回复:] [quote=引用 2 楼 sdghchj 的回复:] 下面的代码表示收到8000个字节后才返回,明显你所有行的数据都在这8000个字节里,而你以为它只是一行数据。 char recv_msg[8000]; memset(recv_msg, 0, 8000); ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0); 直接下面一句就行了,不知道为什么要画蛇添足。 ret = recv(com_Sock, msg2, sizeof(msg2), 0);
编译出错了 error C2664: “int recv(SOCKET,char *,int,int)”: 无法将参数 2 从“TcsvMake *”转换为“char *”[/quote] ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0);[/quote] 还是只能接收到一行数据,难道是发送端发送的数据就不全吗 还是这里阻塞com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);
kk216927 2017-08-23
  • 打赏
  • 举报
回复
引用 14 楼 bie_niu1992 的回复:
[quote=引用 7 楼 bie_niu1992 的回复:] server.cpp recv改成循环接收有试过吗? while(1){ ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0); if(ret >0) { cout << msg2.IP << ","; cout << msg2.C_hao << ","; cout << msg2.EPC << endl; }else break; }
兄弟 我告诉你的这个方法不是可以的嘛
int _tmain(int argc, _TCHAR* argv[])
{
	//创建socket编程环境  
	int ret = 0;
	WSADATA wsadata;
	WORD version = MAKEWORD(2, 0);
	ret = WSAStartup(version, &wsadata);

	//服务器端口创建  
	SOCKET m_hServerSocket;
	m_hServerSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET == m_hServerSocket)
	{
		cout << "服务器socket创建失败!" << endl;
		return 0;
	}
	else
	{
		cout << "服务器socket创建成功" << endl;
	}
	cout << endl;

	//服务器端口绑定  
	SOCKADDR_IN m_addr;
	m_addr.sin_family = AF_INET;
	m_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	m_addr.sin_port = htons(9898);
	ret = bind(m_hServerSocket, (LPSOCKADDR)&m_addr, sizeof(m_addr));


	//服务器端口开始监听  
	ret = listen(m_hServerSocket, 20);//第二个参数指定最大申请的连接数  

	//每当有一个客户端连接申请,则服务器端创建一个线程对其进行处理,模拟数据库服务器的处理方式  
	SOCKET com_Sock;
	SOCKADDR_IN clntaddr;
	int clnlen = sizeof(clntaddr);

	TcsvMake msg2;
	
	while (1)
	{
		int count = 0;
		com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);	
		//获得当前正在通信的socket的IP和端口地址
		getsockname(com_Sock, (SOCKADDR *)&clntaddr, &clnlen);
	
		while(1){
   
			memset(&msg2, 0, sizeof(TcsvMake));
			ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0);
			if(ret >0)
			{	 
				 cout << msg2.IP << ",";
				 cout << msg2.C_hao << ",";
				 cout << msg2.EPC << endl;
			 }else
				break;
		}
    }
    closesocket(com_Sock);
	
	WSACleanup();

	return 0;
}
[/quote] 哎,又可以了,谢谢你啊,还有,我是女生
sdghchj 2017-08-23
  • 打赏
  • 举报
回复
引用 3 楼 zyq_0927 的回复:
[quote=引用 2 楼 sdghchj 的回复:] 下面的代码表示收到8000个字节后才返回,明显你所有行的数据都在这8000个字节里,而你以为它只是一行数据。 char recv_msg[8000]; memset(recv_msg, 0, 8000); ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0); 直接下面一句就行了,不知道为什么要画蛇添足。 ret = recv(com_Sock, msg2, sizeof(msg2), 0);
编译出错了 error C2664: “int recv(SOCKET,char *,int,int)”: 无法将参数 2 从“TcsvMake *”转换为“char *”[/quote] ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0);
kk216927 2017-08-23
  • 打赏
  • 举报
回复
引用 2 楼 sdghchj 的回复:
下面的代码表示收到8000个字节后才返回,明显你所有行的数据都在这8000个字节里,而你以为它只是一行数据。 char recv_msg[8000]; memset(recv_msg, 0, 8000); ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0); 直接下面一句就行了,不知道为什么要画蛇添足。 ret = recv(com_Sock, msg2, sizeof(msg2), 0);
编译出错了 error C2664: “int recv(SOCKET,char *,int,int)”: 无法将参数 2 从“TcsvMake *”转换为“char *”
别逗爷很凶 2017-08-23
  • 打赏
  • 举报
回复
引用 7 楼 bie_niu1992 的回复:
server.cpp
recv改成循环接收有试过吗?

while(1){

ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0);
if(ret >0)
{
cout << msg2.IP << ",";
cout << msg2.C_hao << ",";
cout << msg2.EPC << endl;
}else
break;
}

兄弟 我告诉你的这个方法不是可以的嘛

int _tmain(int argc, _TCHAR* argv[])
{
//创建socket编程环境
int ret = 0;
WSADATA wsadata;
WORD version = MAKEWORD(2, 0);
ret = WSAStartup(version, &wsadata);

//服务器端口创建
SOCKET m_hServerSocket;
m_hServerSocket = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == m_hServerSocket)
{
cout << "服务器socket创建失败!" << endl;
return 0;
}
else
{
cout << "服务器socket创建成功" << endl;
}
cout << endl;

//服务器端口绑定
SOCKADDR_IN m_addr;
m_addr.sin_family = AF_INET;
m_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
m_addr.sin_port = htons(9898);
ret = bind(m_hServerSocket, (LPSOCKADDR)&m_addr, sizeof(m_addr));


//服务器端口开始监听
ret = listen(m_hServerSocket, 20);//第二个参数指定最大申请的连接数

//每当有一个客户端连接申请,则服务器端创建一个线程对其进行处理,模拟数据库服务器的处理方式
SOCKET com_Sock;
SOCKADDR_IN clntaddr;
int clnlen = sizeof(clntaddr);

TcsvMake msg2;

while (1)
{
int count = 0;
com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);
//获得当前正在通信的socket的IP和端口地址
getsockname(com_Sock, (SOCKADDR *)&clntaddr, &clnlen);

while(1){

memset(&msg2, 0, sizeof(TcsvMake));
ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0);
if(ret >0)
{
cout << msg2.IP << ",";
cout << msg2.C_hao << ",";
cout << msg2.EPC << endl;
}else
break;
}
}
closesocket(com_Sock);

WSACleanup();

return 0;
}




kk216927 2017-08-23
  • 打赏
  • 举报
回复
引用 10 楼 bie_niu1992 的回复:
while(int i=0; i *sizeof(TcsvMake) < ret ;i++) 这个打错了 是for(int i=0; i *sizeof(TcsvMake) < ret ;i++)
终于可以了,又加了一个循环

while (1)
	{
		int count = 0;
		com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);
		//获得当前正在通信的socket的IP和端口地址
		getsockname(com_Sock, (SOCKADDR *)&clntaddr, &clnlen);

		/*char recv_msg[8000];
		memset(recv_msg, 0, 8000);
		ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0);*/

         // 一共600行数据
		for (int j = 0; j <600; j++)
		{
            memset(&msg2, 0, sizeof(TcsvMake));
			ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0);

		//直接将接收到的字节流拷贝给相应的结构体即可。    
		for (int i = 0; i *sizeof(TcsvMake) < ret; i++)
		{
			memset(&msg2, 0, sizeof(TcsvMake));
			//memcpy(&msg2, recv_msg + i*sizeof(TcsvMake), sizeof(TcsvMake));
			ret = recv(com_Sock, (char*)&msg2 + i*sizeof(TcsvMake), sizeof(msg2), 0);
			
			cout << msg2.IP << ",";
			cout << msg2.C_hao << ",";
			cout << msg2.EPC << endl;
		}
		}
	}
最后一行还有点问题,不过非常感谢了!
kk216927 2017-08-23
  • 打赏
  • 举报
回复
引用 10 楼 bie_niu1992 的回复:
while(int i=0; i *sizeof(TcsvMake) < ret ;i++) 这个打错了 是for(int i=0; i *sizeof(TcsvMake) < ret ;i++)
之前的代码还是只能打印出第一行数据 改了一下,又只能打印出第二行数据了,这是为什么
while (1)
	{
		int count = 0;
		com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);
		//获得当前正在通信的socket的IP和端口地址
		getsockname(com_Sock, (SOCKADDR *)&clntaddr, &clnlen);

		/*char recv_msg[8000];
		memset(recv_msg, 0, 8000);
		ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0);*/

		memset(&msg2, 0, sizeof(TcsvMake));
		ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0);
		//直接将接收到的字节流拷贝给相应的结构体即可。    
		for (int i = 0; i *sizeof(TcsvMake) < ret; i++)
		{
			
			//memcpy(&msg2, recv_msg + i*sizeof(TcsvMake), sizeof(TcsvMake));
			ret = recv(com_Sock, (char*)&msg2 + i*sizeof(TcsvMake), sizeof(msg2), 0);

			cout << msg2.IP << ",";
			cout << msg2.C_hao << ",";
			cout << msg2.EPC << endl;
		}
		closesocket(com_Sock);
	}
kk216927 2017-08-23
  • 打赏
  • 举报
回复
还是不行,其实我发送文件时,是把每列数据写到结构体里,发送结构体内容,接收到的应该是每列数据的内容,可是每列只有第一行数据被接收到,因此打印出的只有文件第一行内容。
别逗爷很凶 2017-08-23
  • 打赏
  • 举报
回复
while(int i=0; i *sizeof(TcsvMake) < ret ;i++) 这个打错了 是for(int i=0; i *sizeof(TcsvMake) < ret ;i++)
别逗爷很凶 2017-08-23
  • 打赏
  • 举报
回复
改后代码能贴下不?
你server.cpp
while (1)
{
int count = 0;
com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);
//获得当前正在通信的socket的IP和端口地址
getsockname(com_Sock, (SOCKADDR *)&clntaddr, &clnlen);

char recv_msg[8000];
memset(recv_msg, 0, 8000);
ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0);

//直接将接收到的字节流拷贝给相应的结构体即可。
memset(&msg2, 0, sizeof(TcsvMake));
memcpy(&msg2, recv_msg, sizeof(TcsvMake));

cout << msg2.IP << ",";
cout << msg2.C_hao << ",";
cout << msg2.EPC << endl;
}
这段代码recv 8000字节的数 觉得你已经接收不止文件的一行数了 你可以跟踪下ret的值代表接收的数
或者改成
while (1)
{
int count = 0;
com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);
//获得当前正在通信的socket的IP和端口地址
getsockname(com_Sock, (SOCKADDR *)&clntaddr, &clnlen);

char recv_msg[8000];
memset(recv_msg, 0, 8000);
ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0);

//直接将接收到的字节流拷贝给相应的结构体即可。
while(int i=0; i *sizeof(TcsvMake) < ret ;i++)
{

memset(&msg2, 0, sizeof(TcsvMake));
memcpy(&msg2, recv_msg+i*sizeof(TcsvMake), sizeof(TcsvMake));

cout << msg2.IP << ",";
cout << msg2.C_hao << ",";
cout << msg2.EPC << endl;
}
}
kk216927 2017-08-23
  • 打赏
  • 举报
回复
引用 7 楼 bie_niu1992 的回复:
server.cpp recv改成循环接收有试过吗? while(1){ ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0); if(ret >0) { cout << msg2.IP << ","; cout << msg2.C_hao << ","; cout << msg2.EPC << endl; }else break; }
谢谢你,但是刚才试了一下还是不行
别逗爷很凶 2017-08-23
  • 打赏
  • 举报
回复
server.cpp recv改成循环接收有试过吗? while(1){ ret = recv(com_Sock, (char*)&msg2, sizeof(msg2), 0); if(ret >0) { cout << msg2.IP << ","; cout << msg2.C_hao << ","; cout << msg2.EPC << endl; }else break; }
sdghchj 2017-08-22
  • 打赏
  • 举报
回复
下面的代码表示收到8000个字节后才返回,明显你所有行的数据都在这8000个字节里,而你以为它只是一行数据。 char recv_msg[8000]; memset(recv_msg, 0, 8000); ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0); 直接下面一句就行了,不知道为什么要画蛇添足。 ret = recv(com_Sock, msg2, sizeof(msg2), 0);
kk216927 2017-08-22
  • 打赏
  • 举报
回复

//server.cpp   
#include <iostream>  
#include <stdio.h>  
#include <string>  
#include "winsock.h"  
#pragma comment(lib, "wsock32")  
#pragma warning(disable:4996)
using namespace std;

struct TcsvMake
{
	int bianhao;
	string CELLCODE;
	string IP;
	string C_hao;
	int EPC;
	int RCS;
};
int main()
{
	//创建socket编程环境  
	int ret = 0;
	WSADATA wsadata;
	WORD version = MAKEWORD(2, 0);
	ret = WSAStartup(version, &wsadata);

	//服务器端口创建  
	SOCKET m_hServerSocket;
	m_hServerSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET == m_hServerSocket)
	{
		cout << "服务器socket创建失败!" << endl;
		return 0;
	}
	else
	{
		cout << "服务器socket创建成功" << endl;
	}
	cout << endl;

	//服务器端口绑定  
	SOCKADDR_IN m_addr;
	m_addr.sin_family = AF_INET;
	m_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	m_addr.sin_port = htons(10000);
	ret = bind(m_hServerSocket, (LPSOCKADDR)&m_addr, sizeof(m_addr));


	//服务器端口开始监听  
	ret = listen(m_hServerSocket, 20);//第二个参数指定最大申请的连接数  

	//每当有一个客户端连接申请,则服务器端创建一个线程对其进行处理,模拟数据库服务器的处理方式  
	SOCKET com_Sock;
	SOCKADDR_IN clntaddr;
	int clnlen = sizeof(clntaddr);

	TcsvMake msg2;
	
	while (1)
	{
		int count = 0;
		com_Sock = accept(m_hServerSocket, (SOCKADDR *)&clntaddr, &clnlen);	
		//获得当前正在通信的socket的IP和端口地址
		getsockname(com_Sock, (SOCKADDR *)&clntaddr, &clnlen);
	
		char recv_msg[8000];
		memset(recv_msg, 0, 8000);
		ret = recv(com_Sock, recv_msg, sizeof(recv_msg), 0);
	
		//直接将接收到的字节流拷贝给相应的结构体即可。  	
		memset(&msg2, 0, sizeof(TcsvMake));
		memcpy(&msg2, recv_msg, sizeof(TcsvMake));
                
        cout << msg2.IP << ",";
		cout << msg2.C_hao << ",";
		cout << msg2.EPC << endl;
    }
    closesocket(com_Sock);
	
	WSACleanup();

	return 0;
}
只接收到文件第一行数据,请问有什么问题吗?

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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