我正在编写一个客户端/服务器系统,客户端在该系统中从客户端向服务器发送记录。我试图将数据表示为struct
,但我没有在服务器端成功recv()
struct
。
这是我的代码:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#pragma pack(1)
struct emp
{
int id;
char *name;
} emp1, emp3;
#pragma pack(0)
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
memset(recvBuff, '0', sizeof(recvBuff));
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
serv_addr.sin_addr = inet_addr("192.168.0.105");
if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
emp1 = (struct emp *) malloc(sizeof(struct emp));
emp1.name = (char *) malloc((size)*(sizeof(char)));
printf("Enter name of employee : ");
scanf(" %[^\n]s", emp1.name);
printf("Enter emp id : ");
scanf(" %d", &emp1.id);
unsigned char *data = (unsigned char*) malloc(sizeof(regn));
memcpy(data, ®n, sizeof(regn));
sendto(sockfd, data, sizeof(emp1), 0, (SOCKADDR *) &serv_addr,
sizeof(serv_addr));
close(sockfd);
}
我的服务器就像这样
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
struct emp
{
int id;
char *name;
} emp1, emp3;
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
FILE *fp, *fp1;
char recvBuf[1025];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
if(recvfrom(sd, recvBuf, recvBufSize, 0,
(struct sockaddr *) &clientAddr, &len) < 0)
{
printf("Error receiving message from client\n");
}
else
{
printf("Message received:%s\n", recvBuf);
printf("Size :%d\n", strlen(recvBuf));
memcpy(&emp1, recvBuf, sizeof(emp));
printf("name:%s\n", emp1.name );
printf("is:%d\n", emp1.id);
}
答案 0 :(得分:1)
您正在发送一个包含整数和char 指针的结构。该指针指向接收系统上的完全随机位置。
您必须将内容name
发送给。
您可以自己发送结构的每个成员。对于长度可变的成员,您必须先发送大小并在接收端分配它。
正如John Bollinger所说:你的一个结构是打包的,另一个没有。这可能会导致结构的布局和大小出现其他问题,这可能是不必要的。
答案 1 :(得分:0)
添加此答案以回答OP的具体问题。请不要贬低,因为它可能看起来有点偏离原始问题。
简单流式传输的一个例子。这很简单,因为在实际的流式场景中,您需要对象ID才能实例化并加载真实的类。但是如果你已经知道你要发送或接收的是什么课程,他们就不需要这种复杂性了。如果要发送多个类实例,则需要更复杂的流机制。正如微软在MFC中所做的那样,在OWL中的Borland,.NET也有适当的机制,......
namespace OMCIPoco{
typedef std::vector<unsigned char> ucharvector;
SystemData::stream& operator <<(SystemData::stream& stream,const ucharvector& data);
SystemData::stream& operator >>(SystemData::stream& stream,ucharvector& data);
}
cpp文件:
SystemData::stream& operator <<(SystemData::stream& stream,const ucharvector& data)
{
stream << (unsigned long)data.size();
for (ucharvector::const_iterator it=data.begin();it<data.end();++it)
stream << *it;
return stream;
}
SystemData::stream& operator >>(SystemData::stream& stream,ucharvector& data)
{
unsigned long count;
stream >> count;
data.reserve(count);
for (unsigned int i=0;i<count;++i){
unsigned char c;
stream >> c;
data.push_back(c);
}
return stream;
}
注意&lt;&lt;&lt;和&gt;&gt;是平衡的。 流是一个接口,它可以对要流式传输的介质进行抽象,它可以是内存或磁盘,也可以是网络流。我也可以在这里使用流概念解决小端问题,因为流知道如何(de)串行短路,长路,......,并且它也知道如何缓冲。
您可以使用扁平结构以完全避免上述复杂性
class data{
public:
char name[20];
};
现在使用sizeof(data)将是正确的,因为您将发送整个数据结构。我在这里使用了类,但struct的工作方式相同。缺点是,如果名称只包含10个字符,您仍然会发送20个。