分段错误通过 TCP 套接字发送结构

Segmentation fault sending a struct through TCP socket

本文关键字:结构 套接字 TCP 错误 分段      更新时间:2023-10-16

我正在编写一个关于TCP套接字的简单程序。我要做的是将任何 1000 个数据结构从客户端发送到服务器,但它显示分段错误......

这是我的服务器:

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
using namespace std;
#pragma pack(1)
struct student
{
    int id;
    string name;
};
main()
{
   struct sockaddr_in socketInfo;
   socklen_t fromlen;
   int socketHandle;
   int portNumber = 8080;
   bzero(&socketInfo, sizeof(sockaddr_in));  // Clear structure memory
   // create socket
   if((socketHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      close(socketHandle);
      exit(EXIT_FAILURE);
   }
   // Load system information into socket data structures
   socketInfo.sin_family = AF_INET;             //IPv4
   socketInfo.sin_addr.s_addr = htonl(INADDR_ANY); // Use any address available to the system
   socketInfo.sin_port = htons(portNumber);      // Set port number
   // Bind the socket to a local socket address
   if( bind(socketHandle, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) < 0)
   {
      close(socketHandle);
      perror("bind");
      exit(EXIT_FAILURE);
   }
   listen(socketHandle, 1);
   int socketConnection;
   while(1)
   {
   cout<<"Waiting to connect ..."<<endl;
   if( (socketConnection = accept(socketHandle, NULL, NULL)) < 0)
   {
      cout<<"Fail!!"<<endl;
      exit(EXIT_FAILURE);
   }
   //close(socketHandle);
   int rc = 0;  // Actual number of bytes read
   struct student buf;
    while(1)
    {
        rc = recv(socketConnection, &buf, sizeof(struct student)+1, 0);
        cout<<"Recieve = "<<rc<<endl;
        if (rc<=0)
        break;
        cout<<buf.id<<endl;
        cout<<buf.name<<endl;
    }
    }
}

这是我的客户:

#include <iostream>
#include <sstream>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
unsigned long inet_addr(const string a);
string int2str( int val )  // interger convert to string
{  
    ostringstream out;  
    out<<val;  
    return out.str();  
}
#pragma pack(1)
struct student
{
    int id;
    string name;
};
main()
{
   struct sockaddr_in remoteSocketInfo;
   struct hostent *hPtr;
   const char *remoteHost="localhost";
   int socketHandle;
   int portNumber = 8080;
   bzero(&remoteSocketInfo, sizeof(sockaddr_in));  // Clear structure memory
   if((hPtr = gethostbyname(remoteHost)) == NULL)
   {
      cerr << "System DNS name resolution not configured properly." << endl;
      cerr << "Error number: " << ECONNREFUSED << endl;
      exit(EXIT_FAILURE);
   }

   if((socketHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      close(socketHandle);
      exit(EXIT_FAILURE);
   }
   // Load system information into socket data structures
   memcpy((char *)&remoteSocketInfo.sin_addr, hPtr->h_addr, hPtr->h_length);
   remoteSocketInfo.sin_family = AF_INET;
   remoteSocketInfo.sin_port = htons(portNumber);      // Set port number
   if(connect(socketHandle, (struct sockaddr *)&remoteSocketInfo, sizeof(sockaddr_in)) < 0)
   {
      close(socketHandle);
      exit(EXIT_FAILURE);
   }
   struct student buf[1000];
    for (int i=0; i<1000; i++)
    {
        buf[i].id = i+1;
        buf[i].name = "student_" + int2str(i) + "00";
        send(socketHandle, &buf[i], sizeof(struct student)+1, 0);
    }
}

结果:

Waiting to connect ...
Recieve = 13
1
Segmentation fault (core dumped)

这里的问题是struct student中的一个字段是std::string对象。这不能像您那样直接通过电线发送。

相反,要么将其更改为固定大小的字符数组,如下所示...

struct student
{
    int id;
    char name[100];
}

。并在那里写下你的名字。或者,您必须以不同的方式通过网络发送它。