tcp上的可变长度消息

时间:2016-02-01 10:19:01

标签: c sockets client-server

我正在尝试在TCP中发送可变长度消息,但消息长度为     打印总是0.我使用beej指南代码发送和接收和打包和解包发送标题长度。有人请指出错误。

服务器代码

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

#define MAX_SIZE 50

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


void packi32(unsigned char *buf, unsigned long i)//from beej guide
{
     *buf++ = i>>24; *buf++ = i>>16;
     *buf++ = i>>8; *buf++ = i;
}

/* sends all data - thanks to Beej's Guide to Network Programming */
int sendall(int s, char *buf, int *len)
{
   int total=0;
   int bytesleft=*len;
   int n=0;

   /* send all the data */
   while(total<*len){

    /* send some data */
    n=send(s,buf+total,bytesleft,0);

    /* break on error */
    if(n==-1)
        break;

    /* apply bytes we sent */
    total+=n;
    bytesleft-=n;
        }

/* return number of bytes actually send here */
*len=total;

/* return -1 on failure, 0 on success */
return n==-1?-1:0;
}

int sendus(int s,char *msg)
{
    char buf[4];//here 4 is header length
    int len = strlen(msg);
    packi32(buf,len);
    int ll = 4;// ll is header length containing message length
    int x;
    if((x = sendall(s,buf,&ll))< 0)
        printf("value of sent x %d\n",x);

    int y = sendall(s,msg,&len);
    return y;
}

int main(int argc, char *argv[])
{
    int sockfd, newsockfd, portno;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;

    if (argc < 2) 
   {
        fprintf(stderr,"ERROR, no port provided\n");
        exit(1);
    }

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (sockfd < 0) 
        error("ERROR opening socket");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);
    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);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);


if (newsockfd < 0) 
        error("ERROR on accept");

char msg[1024] = "hello";
int xx = sendus(sockfd,(char*)msg);


   close(newsockfd);

    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 <netinet/in.h>
#include <netdb.h> 
#include<errno.h>
void error(const char *msg)
{
   perror(msg);
   exit(0);
}

/** unpacki32() -- unpack a 32-bit int from a char buffer (like ntohl())
*/
unsigned long unpacki32(unsigned char *buf)
{
  return (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
}

/* receives all data - modelled after sendall() */
int recvall(int s, char *buf, int *len, int timeout){
int total=0;
int bytesleft=*len;
int n=0;
time_t start_time;
time_t current_time;

/* clear the receive buffer */
bzero(buf,*len);

time(&start_time);

/* receive all data */
while(total<*len){

    /* receive some data */
    n=recv(s,buf+total,bytesleft,0);

    /* no data has arrived yet (non-blocking socket) */
    if(n==-1 && errno==EAGAIN){
        time(&current_time);
        if(current_time-start_time>timeout)
            break;
        sleep(1);
        continue;
            }

    /* receive error or client disconnect */
    else if(n<=0)
        break;

    /* apply bytes we received */
    total+=n;
    bytesleft-=n;
        }

/* return number of bytes actually received here */
*len=total;

/* return <=0 on failure, bytes received on success */
return (n<=0)?n:total;
    }

int recvme(int s, char *buf)
{
    char len[4];
    int l = 4;
    int n = recvall(s,len,&l,10);
    int msg_len = unpacki32(len);
    printf("msg_length :%d",msg_len);

    int z ;
    z = recvall(s,buf,&msg_len,10);

    return z;
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    char buffer[1024];
    if (argc < 3) 
{
    fprintf(stderr,"usage %s hostname port\n", argv[0]);
    exit(0);
    }
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");

server = gethostbyname(argv[1]);
    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");
        n = recvme(sockfd, buffer);
        if (n < 0) 
            error("ERROR reading from socket");


    printf("%s\n",buffer);

    close(sockfd);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

失败的根本原因在于服务器的行

int xx = sendus(sockfd,(char*)msg);

- sockfdlisten()套接字,但我们必须使用从newsockfd返回的accept(),i。即

    sendus(newsockfd, msg);