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());
            }
        }
    }
};
相关推荐
Oll Correct44 分钟前
实验二十九:TCP的运输连接管理
网络·笔记
日取其半万世不竭3 小时前
iftop、nethogs 和 nload:Linux 服务器网络流量实时监控工具介绍
linux·运维·服务器
mounter6253 小时前
Linux 内核资源管理:控制组(cgroup)的演进与“策略组”新提案
linux·运维·服务器·cgroup·kernel
bksczm3 小时前
文件在磁盘中的存储方式
linux·运维·服务器
L1624763 小时前
OpenSSH 半自动升级方案(独立编译 + 手动迁移 + 重建 systemd 服务)
linux·服务器·ssh
半旧夜夏3 小时前
【保姆级】微服务组件环境搭建(Docker Compose版)
java·linux·spring cloud·微服务·云原生·容器
Cheng小攸3 小时前
综合实验2
网络·windows
Soari4 小时前
SSH 主机密钥冲突
运维·网络·ssh
爱莉希雅&&&4 小时前
zabbix快速搭建和使用
android·linux·数据库·zabbix·监控
z200509304 小时前
【linux学习】深入理解linux文件I/O,从C标准库到内核态
linux·学习·操作系统