没有从客户端发送的服务器上获取确切的数据

时间:2015-07-21 16:05:48

标签: c linux sockets struct client-server

我正在编写一个客户端/服务器系统,客户端在该系统中从客户端向服务器发送记录。我试图将数据表示为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, &regn, 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);
    }

2 个答案:

答案 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个。