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());
            }
        }
    }
};
相关推荐
zzzzzz3101 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode1 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
A小辣椒3 天前
TShark:Wireshark CLI 功能
linux
A小辣椒3 天前
TShark:基础知识
linux
AlfredZhao3 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao4 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334664 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪4 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠5 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush45 天前
嵌入式linux学习记录十四、术语
linux·嵌入式