【问题标题】:C++ Sending and Receiving TCP/IP structureC++ 发送和接收 TCP/IP 结构
【发布时间】:2015-08-14 06:56:04
【问题描述】:

这是我的客户:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <string.h>

using namespace std;

typedef struct TEMPIO
{
    unsigned int id;
    unsigned short messageSender;
    unsigned short length;
    unsigned int secs;
    unsigned int usecs;
    unsigned short videoId;
    unsigned short outChannel;
}TEMPIO_msg;

int client();
int server();
void error();


void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(){
    int sockfd, portno, n;
    char * address;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    TEMPIO_msg message;
    struct timeval time;

    portno=2015;//TBD take portno
    address="127.0.0.1";//TBD take address

    message.id=htonl(1694367746);
    message.messageSender=htons(100);
    message.length=htons(20);
    gettimeofday(&time,NULL); 
    message.secs=htonl(time.tv_sec);
    message.usecs=htonl(time.tv_usec);
    message.videoId=htons(44);
    message.outChannel=htons(38);

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0){
        error("ERROR opening socket");
        exit(0);
    }

    server = gethostbyname(address);
    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
    serv_addr.sin_port = htons(portno);

    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
        error("ERROR connecting");
        exit(0);
    }

    while(true){
        if (sendto(sockfd,&message,sizeof(TEMPIO_msg),MSG_EOR,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        {
            perror("sendto");
            exit(1);
        }else{
            printf("CLI: sent something...\n"); 
        }
        sleep(3);
    }

    close(sockfd);
    return 0;
}

这是我的服务器:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <string.h>

using namespace std;

typedef struct TEMPIO
{
    unsigned int id;
    unsigned short messageSender;
    unsigned short length;
    unsigned int secs;
    unsigned int usecs;
    unsigned short videoId;
    unsigned short outChannel;
}TEMPIO_msg;

int client();
int server();
void error();


void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(){
    int sockfd, newsockfd, portno;
    char * address;
    socklen_t clilen;
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    TEMPIO_msg message;
    struct timeval time;

    address="127.0.0.1";
    portno = 2015; // TBD

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) error("ERROR opening socket");

    bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
    listen(sockfd,5);
    clilen = sizeof(cli_addr);
    printf("SRV: started! \n");
    newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0) error("ERROR on accept");
    printf("SRV: client connected! \n");

    printf("SRV: Listening... ");
    if (recvfrom(sockfd,&message,sizeof(TEMPIO_msg),MSG_PEEK,(struct sockaddr *) &cli_addr, &clilen) > 0) 
    {
        printf("SRV catched something!\n");
    }
    close(newsockfd);
    close(sockfd);
    return 0; 

}

如您所见,我使用以下函数来发送/接收数据结构:

ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
       int flags, struct sockaddr *restrict address,
       socklen_t *restrict address_len);
ssize_t sendto(int socket, const void *message, size_t length,
       int flags, const struct sockaddr *dest_addr,
       socklen_t dest_len);

我的代码已正确编译,但无法正常工作。 很奇怪,因为我在客户端之后启动服务器,服务器似乎在这一点上卡住了:

$ ./srv SRV: started!
SRV: client connected!

客户端正确发送数据包,服务器仅在客户端发送 4 次后才继续执行

$ ./cli 
CLI: sent something...
CLI: sent something...
CLI: sent something...
CLI: sent something...

这太奇怪了,因为如您所见,服务器似乎卡在两个 printf 之间(客户端已连接和正在侦听):

./srv SRV: started! 
SRV: client connected! 
SRV: Listening... 

你能看出哪里不对吗?

【问题讨论】:

  • 当然这将取决于编译器/系统,但看起来 TEMPIO_msg 可能是 20 个字节。您是否在客户端和服务器上都做了sizeof(TEMPIO_msg) 并查看了每个结构成员变量的相对偏移地址?它们有可能被包装成不同的尺寸,或者在不同的地方装满了填充物。

标签: c++ sockets tcp


【解决方案1】:

您在服务器中的recvfrom 调用正在尝试从sockfd 读取,这是侦听套接字。您应该改为从newsockfd 读取,这是连接的套接字。

另外,您应该将recvfrom 的返回值复制到一个变量中。您将首先检查它是否为 -1,在这种情况下您将处理错误。如果没有,您将检查以确保您读取了预期的字节数。

关于recvfrom:那和sendto都应该分别替换为recvsend,因为你正在处理一个TCP套接字;所以端点是已知的。

【讨论】:

  • 感谢有关接收和发送的建议!是的......错误是来自sockfd而不是newsockfd的读数......啊:)
猜你喜欢
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
  • 2013-06-28
  • 2012-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多