C++ TCP socket通信

3 篇文章 0 订阅

实现了C++下的TCP socket通信。由于不知道发送/接收信息的长度,因此,实现中先发送消息的长度,然后再发送消息内容;接收也一样,先接收消息长度,然后再接收消息的具体内容。实现代码在Linux下测试通过。

原来写的程序是有问题的,当发送的报文太长时,接收到的报文与发送的报文并不是一致的(接收到的报文不全)。找了一些资料发现“如果是阻塞的:man中的说明: 
It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because  we  were  close  to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. 
如果是非阻塞,因为可能读的时候所有的数据还没有接收完,read只返回当前socket缓冲中有的数据。”(http://bbs.byr.cn/#!article/Linux/106207

修改后的server端程序如下。

server端的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
using namespace std;

void error(const string msg)
{
    perror(msg.c_str());
    exit(1);
}

void send_msg(int &sockfd, const string message)
{
    int n = 0;    
    int length = message.length();

    n = write(sockfd, (char *) &length, sizeof(length));
    if(n < 0)
    {
        error("Error: cannot send message length to server!\n");
    }
    
    n = write(sockfd, message.c_str(), length);
    if(n < 0)
    {
        error("Error: cannot send message to server!\n");
    }
}

void recv_msg(int &sockfd)
{
    int n = 0;
    // fisrt accept the length of message
    int length = 0;
    n = read(sockfd, (char *) &length, sizeof(length));
    cout << "MSG Length: " << length << endl;
    if(n < 0)
    {
        error("Error: cannot read message length from client!\n");
    }

    // receive message from client
    int buffer_length = length + 1;
    char * buffer = new char[buffer_length];
    bzero(buffer, buffer_length);
    int byte_read = 0;
    while(byte_read < length)
    {
        n = read(sockfd, buffer + byte_read, length - byte_read);
        if(n < 0)
        {
            error("Error: cannot read message from client!\n");
        }
        byte_read += n;
    }

    cout << "MSG: " << buffer << endl;
}

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

    if(argc < 2)
    {
        error("Error: no port provided!\n");
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        error("Error: cannot open socket!\n");
    }

    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: binding error!\n");
    }

    listen(sockfd, 5); // backlog = 5, defines the maximum length to which the queue of pending connections for sockfd may grow
    clilen = sizeof(cli_addr);
    while(1)
    {
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if(newsockfd < 0)
        {
            error("Error: cannot accept!\n");
        }

        // recieve message
        cout << "receiving message...\n";
        recv_msg(newsockfd);
        cout << "******************************\n";

        // send message to client
        cout << "sending message...\n";
        send_msg(newsockfd, "Successfully received!");
        close(newsockfd);
    }

    close(sockfd);
    return 0;
}


client端的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <iostream>
using namespace std;

void error(const string msg)
{
    perror(msg.c_str());
    exit(1);
}

void send_msg(int &sockfd, const string message)
{
    int n = 0;    
    int length = message.length();

    n = write(sockfd, (char *) &length, sizeof(length));
    if(n < 0)
    {
        error("Error: cannot send message length to server!\n");
    }
    
    n = write(sockfd, message.c_str(), length);
    if(n < 0)
    {
        error("Error: cannot send message to server!\n");
    }
}

void recv_msg(int &sockfd)
{
    int n = 0;
    // fisrt accept the length of message
    int length = 0;
    n = read(sockfd, (char *) &length, sizeof(length));
    cout << "MSG Length: " << length << endl;
    if(n < 0)
    {
        error("Error: cannot read message length from client!\n");
    }

    // receive message from client
    int buffer_length = length + 1;
    char * buffer = new char[buffer_length];
    bzero(buffer, buffer_length);
    int byte_read = 0;
    while(byte_read < length)
    {
        n = read(sockfd, buffer + byte_read, length - byte_read);
        if(n < 0)
        {
            error("Error: cannot read message from client!\n");
        }
        byte_read += n;
    }

    cout << "MSG: " << buffer << endl;
}

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

    // char buffer[256];

    if(argc < 3)
    {
        error("Error! Usage: cmd hostname port\n");
    }
    
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        error("Error: cannot open socket!\n");
    }

    server = gethostbyname(argv[1]);
    if(server == NULL)
    {
        error("Error: cannot find the server!");
    }

    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: cannot connect to server!\n");
    }
    
    cout << "Please enter the message: \n";
    string message = "";
    getline(cin, message);
  
    // send message
    cout << "sending message...\n";
    send_msg(sockfd, message);

    // receive message from server
    cout << "receiving message...\n";
    recv_msg(sockfd);
    cout << "******************************\n";
    
    close(sockfd);
    return 0;
}

执行结果如下图所示:



参考文献:

http://www.linuxhowtos.org/C_C++/socket.htm

http://stackoverflow.com/questions/666601/what-is-the-correct-way-of-reading-from-a-tcp-socket-in-c-c

http://bbs.byr.cn/#!article/Linux/106207

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值