回声客户端

socket 编写客户端与服务端代码

客户端代码

/**
  * 客户端代码,每次将写入服务端的数据再读回来,利用 read 以及 write 函数完成 socket 读写
  */
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>

int main(int argc, char **argv) {
    int sock;
    char message[1024];
    int str_len;
    struct sockaddr_in server_addr;
    if(argc != 3) {
        std::cerr << "Usage:" << argv[0] << std::endl;
        exit(1);
    }
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock == -1) {
        std::cerr << "socket error" << std::endl;
        exit(1);
    }
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    server_addr.sin_port = htons(atoi(argv[2]));
    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        std::cerr << "Error connecting" << std::endl;
        exit(1);
    }
    std::cout << "connecting********************************" << std::endl;
    while(1) {
        std::cout << "input message(Q to quit) :" << std::endl;
        std::string buff;
        std::cin >> buff;
        if(buff == "Q" || buff == "q") {
            break;
        }
        str_len = write(sock, buff.c_str(), buff.size());
        int recv_len = 0;
        int recv_cnt;
		/**
		  * 读取数据不应该一次性读出,因为TCP连接是字节流传输,很有可能没有读到边界,所以应该设置为循环读取,保证读取到的数据跟写入的数据保持一致
		  */
        while (recv_len < str_len) {
            recv_cnt = read(sock, message, 1024);
            if(recv_cnt == -1) {
                std::cout << "read error" << std::endl;
                exit(1);
            }
            recv_len += recv_cnt;
        }
        message[recv_len] = '\0';
        // str_len = read(sock, message, 1024);
        // message[str_len] = '\0';
        std::cout << message << std::endl;
    }
    close(sock);
    return 0; 
}

服务端代码

/**
  * 最多完成五次客户端到服务端的连接,服务端调用顺序为 : 
  * 1. 创建 socket
  * 2. 命名 socket
  * 3. 监听 socket
  * 4. 接受 socket // 接受 socket 后会创建一个新 socket 通信
  * 5. 读写 socket
  */
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>


int main(int argc, char **argv) {
    int server_socket, client_socket;
    char message[1024];
    int str_len, i;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_sz;
    if(argc != 2) {
        std::cerr << "Usage: " << argv[0] << std::endl;
        exit(1);
    }
    server_socket = socket(PF_INET, SOCK_STREAM, 0);
    if(server_socket < 0) {
        std::cerr << "socket error" << std::endl;
        exit(1);
    }
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(atoi(argv[1]));
    if(bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
        std::cerr << "bind error" << std::endl;
        exit(1);
    }
    if(listen(server_socket, 5) == -1) {
        std::cerr << "listen error" << std::endl;
        exit(1);
    }
    client_addr_sz = sizeof(client_addr);
    for (int i = 0; i < 5; i++) {
        client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &client_addr_sz);
        if(client_socket == -1) {
            std::cerr << "accept error" << std::endl;
            exit(1);
        }
        else {
            std::cout << "connected client" << i + 1 << std::endl;
        }
        while((str_len = read(client_socket, message, 1024)) != 0) {
            write(client_socket, message, str_len);
        }
        close(client_socket);
    }
    close(server_socket);
    return 0;
}
posted @ 2021-04-21 20:29  witchers  阅读(77)  评论(0)    收藏  举报