当前位置:   article > 正文

socket编程实现TCP通信

socket编程实现TCP通信

socket编程实现TCP通信

tcp_client.cc

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>
#include <cerrno>
#include "log.hpp"
#define SIZE 1024
uint16_t serverport;
std::string serverip;
void *tcpSend(void *args)
{
    int sock = *(int *)args;

    std::string message;
    while (true)
    {
        std::cerr << "请输入你的信息# ";
        std::getline(std::cin, message);
        send(sock, message.c_str(), message.size(), 0);
    }
}

void *tcpRecv(void *args)
{
    int sock = *(int *)args;
    char buff[1024];
    while (true)
    {
        ssize_t s = recv(sock, buff, sizeof(buff) - 1, 0);
        if (s > 0)
        {
            buff[s] = '\0';
            printf("%s\n", buff);
            fflush(stdout);
        }
    }
}
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cout << "Usage: " << argv[0] << " ip port" << std::endl;
        exit(1);
    }
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        std::cerr << "FATAL " << errno << ":" << strerror(errno);
        exit(2);
    }

    serverport = atoi(argv[2]);
    serverip = argv[1];

    struct sockaddr_in server;
    memset(&server, 0, sizeof server);
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    server.sin_addr.s_addr = inet_addr(serverip.c_str());

    if (connect(sock, (struct sockaddr*)&server, sizeof(server)) == -1) {
        printf("连接失败 [%d:%s]\n",errno,strerror(errno));
        close(sock);
        exit(1);
    }
    LogMessage(NORMAL,"connect success");

    pthread_t t1, t2;
    pthread_create(&t1, nullptr, tcpSend, (void *)&sock);
    pthread_create(&t2, nullptr, tcpRecv, (void *)&sock);

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);

    close(sock);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

tcp_server.cc

#include "tcp_server.hpp"
int main(int argc,char* argv[])
{
    if(argc != 2)
    {
        std::cout<<"Usage: "<<argv[0]<<" port"<<std::endl;
        exit(1);
    }
    uint16_t port = atoi(argv[1]);
    TcpServer* svr = new TcpServer(port);
    svr->initServer();
    svr->start();
    delete svr;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

tcp_server.hpp

#ifndef UDP_SERVER_HPP
#define UDP_SERVER_HPP

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unordered_map>
#include <unistd.h>
#include <signal.h>
#include <wait.h>
#include "log.hpp"

#define SIZE 1024

static void service(int sock, std::string &client_ip, uint16_t &client_port)
{
    char buff[1024];
    while (true)
    {
        ssize_t s = read(sock, buff, sizeof(buff) - 1);
        if (s > 0)
        {
            buff[s] = '\0';
            printf("[%s:%d]# %s\n", client_ip.c_str(), client_port, buff);
        }
        else if (s == 0)
        {
            LogMessage(NORMAL, "[%s:%d] shutdown, me too!", client_ip.c_str(), client_port);
            break;
        }
        else
        {
            LogMessage(ERROR, "read socket error, %d:%s", errno, strerror(errno));
            break;
        }
        write(sock, buff, strlen(buff));
    }
}
struct ThreadData
{
    int _sock;
    std::string _ip;
    uint16_t _port;
};
class TcpServer
{
private:
    const int gbacklog = 20;

public:
    static void* threadRoutine(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData* td = (ThreadData*)args;
        service(td->_sock, td->_ip, td->_port);
        delete td;
        return nullptr;
    }
    TcpServer(uint16_t port, std::string ip = "0.0.0.0")
        : _port(port), _listensock(-1),_ip(ip)
    {
    }
    void initServer()
    {
        // 创建套接字
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock < 0)
        {
            LogMessage(FATAL, "socket error, %d:%s", errno, strerror(errno));
            exit(2);
        }
        // 绑定
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = inet_addr(_ip.c_str());
        if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            LogMessage(FATAL, "bind error, %d:%s", errno, strerror(errno));
            exit(3);
        }
        // 建立连接(监听)
        if (listen(_listensock, gbacklog) < 0)
        {
            LogMessage(FATAL, "listen error, %d:%s", errno, strerror(errno));
            exit(4);
        }
        LogMessage(NORMAL, "init TCP server success, listensock: %d", _listensock);
    }
    void start()
    {
        signal(SIGCHLD,SIG_IGN);//不理会子进程 v2.1
        while (true)
        {
            // 获取连接
            struct sockaddr_in src;
            socklen_t len = sizeof(src);
            int servicesock = accept(_listensock, (struct sockaddr *)&src, &len);
            std::cout<<servicesock<<std::endl;
            if (servicesock < 0)
            {
                LogMessage(ERROR, "accept error, %d:%s", errno, strerror(errno));
                continue;
            }
            uint16_t client_port = ntohs(src.sin_port);
            std::string client_ip = inet_ntoa(src.sin_addr);
            LogMessage(NORMAL, "link success, [%s:%d]", client_ip.c_str(), client_port);
            // 获取连接成功,开始通信服务
            // v1 单进程循环
            //service(servicesock, client_ip, client_port);

            //v2.0 多进程
            // pid_t id = fork();
            // if(id == 0)
            // {
            //     close(_listensock);
            //     service(servicesock, client_ip, client_port);
            //     exit(0);
            // }
            // close(servicesock);

            //v2.1 多进程
            // pid_t id = fork();
            // if(id == 0)
            // {
            //     close(_listensock);
            //     if(fork() > 0) exit(0);
            //     service(servicesock, client_ip, client_port);
            // }
            // waitpid(id,nullptr,0);
            // close(servicesock);

            //v3 多线程
            ThreadData* td = new ThreadData;
            td->_sock = servicesock;
            td->_ip = client_ip;
            td->_port = client_port;
            pthread_t tid;
            pthread_create(&tid,nullptr,threadRoutine,(void*)td);
            close(servicesock);


        }
    }

private:
    uint16_t _port;
    std::string _ip;
    int _listensock;
};
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154

log.hpp

#pragma once
#include<iostream>
#include<cstdio>
#include<cstdarg>
#include<ctime>
#include<string>

#define DEBUG   0
#define NORMAL  1
#define WARNING 2
#define ERROR   3
#define FATAL   4
const char* gLevelMap[]={"DEBUG","NORMAL","WARNING","ERROR","FATAL"};

void LogMessage(int level,const char* format,...)
{
    char stdBuffer[1024] = {'\0'};
    time_t timestamp = time(nullptr);
    snprintf(stdBuffer,sizeof stdBuffer,"[%s] [%ld]",gLevelMap[level],timestamp);

    char logBuffer[1024] = {'\0'};;
    va_list args;
    va_start(args,format);
    vsnprintf(logBuffer,sizeof logBuffer,format,args);
    va_end(args);
    printf("%s%s\n",stdBuffer,logBuffer);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

makefile

.PHONY:add
all:tcp_client tcp_server
tcp_client:tcp_client.cc
	g++ -o $@ $^ -std=c++11 -l pthread
tcp_server:tcp_server.cc
	g++ -o $@ $^ -std=c++11 -l pthread
.PHONY:clean
clean:
	rm -f tcp_client tcp_server
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/451907
推荐阅读
  

闽ICP备14008679号