TCP外壳

TCP与UDP的接口基本一样,多添加了3个接口。

1. listen

复制代码
int listen (int __fd, int __n);
On success, zero is returned.  
On error, -1 is  returned, and errno is set to indicate the error.

监听_fd对应的端口号,相当于站在外面的接客员,一旦有cilent需要建立通信的请求,就会通知里面的招待员。

2. accpept

复制代码
int accept (int __fd, __SOCKADDR_ARG __addr,
		   socklen_t *__restrict __addr_len);
 On  success,  these  system calls return a file de‐scriptor 
 for the accepted socket (a nonnegative integer).  
 On error, -1 is returned, errno is set to indicate the error, 
 and addrlen is left unchanged.

相当于接待员,将顾客从门外引入屋内,并分配一个小间fd(文件描述符),

用于与cilent后续进行交流,输入和输出,与文本无异,都是写入用户缓冲区,

有OS决定是写入硬盘,还是写入网络。

3. connect

复制代码
int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
 If the connection or binding succeeds, zero is  returned.  
 On error, -1 is returned, and errno is set to indicate the error.

addr就是struct sockaddr_in 输入型函数,保存了需要访问客户端的ip,端口。使用connect将cilent的套接字(也可以直接write和read)发送请求建立通信给server。

完整代码

makefile

复制代码
all:server.out cilent.out

server.out:server.cpp
	g++ -o server.out server.cpp
cilent.out:cilent.cpp
	g++ -o cilent.out cilent.cpp

.PHONY:clean
clean:
	rm -rf *.out

server.cpp

复制代码
#include<iostream>
#include<memory>
#include"server.h"
using namespace std;
void manual()
{
    printf("use manual: \n            filename:        port: \n");
}
int main(int argc,const char* argv[])
{
    if(argc!=2)
    {
        manual();
        exit(2);
    }
    string port=argv[1];
    unique_ptr<server> myserver(new server(stoi(port)));
    myserver->Init();
    myserver->start();
    return 0;
}

server.h

复制代码
#include <iostream>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <error.h>
#include <unistd.h>
using namespace std;

#define DeafultIp "0.0.0.0"

class server
{
    int16_t port;
    string ip;
    int sockfd;

public:
    server(int16_t _port, string _ip = DeafultIp) : port(_port), ip(_ip) {}
    ~server() {}
    void Init()
    {
        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        struct sockaddr_in servermessage;
        servermessage.sin_family = AF_INET;
        servermessage.sin_port = htons(port);
        servermessage.sin_addr.s_addr = htonl(INADDR_ANY);
        socklen_t len = sizeof(servermessage);

        if (bind(sockfd, (struct sockaddr *)&servermessage, len) == -1) // 0成功
        {
            cout << "error: " << strerror(errno) << endl;
            exit(2);
        }

        if (listen(sockfd, 0) == -1) // 监听端口
        {
            cout << "error: " << strerror(errno) << endl;
            exit(2);
        }
    }

    void start()
    {
        struct sockaddr_in cilentmess;
        socklen_t len = sizeof(cilentmess);
        int acceptsock = accept(sockfd, (struct sockaddr *)&cilentmess, &len);
        if (acceptsock == -1) // 0成功
        {
            cout << "error: " << strerror(errno) << endl;
            exit(2);
        }
        int16_t port=ntohs(cilentmess.sin_port);
        string ip=inet_ntoa(cilentmess.sin_addr);
        char buffer[1024];
        while (1)
        {
            int ret = read(acceptsock, buffer, sizeof(buffer));
            if (ret > 0)
            {
                buffer[ret] = 0;
                cout<<"ip: "<<ip<<"  port: "<<port<<" : "<<buffer<<endl;
            }
        }
    }
};

cilent.cpp

复制代码
#include<iostream>
#include<memory>
#include"cilent.h"
using namespace std;

void manual()
{
    printf("use manual: \n            filename:       ip:      port: \n");
}
int main(int argc,const char* argv[])
{
    if(argc!=3)
    {
        manual();
        exit(2);
    }
    string port=argv[2];
    string ip=argv[1];
    unique_ptr<cilent> mycilent(new cilent(stoi(port),ip));
    mycilent->Init();
    mycilent->start();
    return 0;
}

cilent.h

复制代码
#include <iostream>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <error.h>
#include <unistd.h>
using namespace std;

class cilent
{
    int16_t port;
    string ip;
    int sockfd;

public:
    cilent(int16_t _port, string _ip) : port(_port), ip(_ip) {}
    ~cilent() {}

    void Init()
    {
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1)
        {
            cout << "error: " << strerror(errno) << endl;
            exit(2);
        }
        struct sockaddr_in servermess;
        servermess.sin_family = AF_INET;
        servermess.sin_port = htons(port);
        servermess.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof(servermess);

        if (connect(sockfd,(struct sockaddr*)& servermess,len)!=0)
        {
            cout<<"error: "<<strerror(errno)<<endl;
            exit(2);
        }
    }

    void start()
    {
        char buffer[1024];
        while (1)
        {
            cout << "Please Enter: ";
            if (fgets(buffer, sizeof(buffer), stdin))
            {
                string send_=buffer;
                send_[send_.size()-1]=0;
               write(sockfd,send_.c_str(),send_.size());
            }
        }
    }
};
相关推荐
上海云盾-高防顾问1 小时前
什么是IP访问数据?
网络·网络协议·tcp/ip
sanguine_boy1 小时前
csv、log、txt文件过大,需要拆分成多个文件
linux
@insist1231 小时前
信息安全工程师-主动防御体系核心技术:从监测溯源到隐私保护全解析
网络·安全·软考·信息安全工程师·软件水平考试
德迅云安全-小潘1 小时前
游戏行业如何保障网络安全
服务器·网络·游戏
QYR_111 小时前
2026年MT 插芯市场洞察:CAGR 7.9%,2032 年全球规模将达 4.6 亿美元
网络·数据库·人工智能
HalvmånEver1 小时前
MySQL 使用 C 语言连接
linux·数据库·学习·mysql
星恒讯工业路由器1 小时前
SYN Flood攻击与防护:工业路由器安全
网络·智能路由器
南京码讯光电技术有限公司1 小时前
2026年国内工业路由器技术分析与FAQ
网络·智能路由器·工业通信·工业无线覆盖
@encryption1 小时前
计算机网络 --- STP
网络·计算机网络