ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

套接字编程__tcp

2020-03-16 14:06:38  阅读:207  来源: 互联网

标签:__ return addr int sock tcp sockfd 接字


套接字编程__tcp

tcp:传输控制协议:面向连接,可靠传输,面向字节流;应用场景就是数据安全性大于实时性的场景—文件传输。(不限制上层传输数据大小的传输方式)

udp网络通信程序流程:
在这里插入图片描述
socket接口介绍:
1.创建套接字

int socket(int domain, int type, int protocol)

domain:地址域 ---- 不同的网络地址结构 AF-INET (IPv4地址域)
type: 套接字类型 — 流式套接字/数据报套接字
流式套接字: 一种有序的,可靠的,双向的,基于连接的字节流传输 SOCK_STREAM
数据报套接字:无连接的,不可靠,有最大长度限制的传输 SOCK_DGRAM
protocol:使用协议 0----不同套接字类型下的默认协议:流式套接字tcp/数据报套接字默认是udp
IPPROTO_TCP — tcp协议 IPPROTO_UDP — udp协议
返回值:返回套接字的操作句柄-----文件描述符

2.绑定地址信息

int bind(int sockfd, struct sockaddr* addr, socklen_t len);

sockfd:创建套接字返回的操作句柄。
addr: 要绑定的地址信息结构
len:地址信息的长度
返回值:成功返回0;失败返回-1。

3.服务端开始监听

int listen(int sockfd, int backlog);

backlog:决定同一时间,服务端所能接受的客户端连接请求,但不能决定服务端能够接受多少客户端的参数。
有一个 connection pending queue 可以表示能够接受多少客户端的参数。若队列放满了,则将后续请求丢弃。

4.获取新建socket的操作句柄

int accept(int sockfd, struct sockaddr* addr, socklen_t *len);

sockfd: 监听套接字 — 指定要获取哪个pending queue中的套接字
addr : 获取一个套接字,这个套接字与指定的客户端通信,通过addr获取这个客户端信息
len:指定地址信息想要的长度以及返回实际的地址长度
返回值: 成功返回新获取的套接字的描述符; 失败返回-1;

5.接收数据

ssize_t recv(int sockfd, char *buf, int len, int flag);

sockfd:套接字操作句柄
buf: 缓冲区首地址,用于存放接收到的数据,从内核socket接收缓冲区中取出数据放入这个buf用户态缓冲区。
len: 用户想要读取的数据长度,但不能大于buf缓冲区的长度。
flag: 0 —默认阻塞操作–若缓冲区中没有数据则一直等待 MSG_DONTWAIT—非阻塞
返回值: 成功返回实际读取到的数据字节长度;连接断开返回0; 失败返回-1;

6.发送数据

ssize_t send(int sockfd, char* data, int len, int flag);

sockfd:套接字操作句柄,发送数据就是将数据拷贝到内核socket发送缓冲区中
data: 要发送的数据的首地址
int_len: 要发送的数据的长度
flag: 选项参数 默认为0—表示当前操作时阻塞操作 MSG_DONTWAIT —设置为非阻塞
如果发送数据时,socket发送缓冲区已经满了,则0默认阻塞等待;MSG_DONTWAIT就会立即报错返回。
返回值: 成功返回实际发送的的数据字节长度; 失败返回-1;若连接断开则触发异常,进程退出。

7.关闭套接字

int close(int fd);

8.客户端向服务端发送连接请求

int connect(int sockfd, int sockaddr* addr, socklen_t len);

sockfd:客户端套接字—若还未绑定地址,则操作系统会选择合适的源端地址进行绑定
addr: 服务端地址信息
len; 地址信息长度。

9.代码
1.tcpsocket.hpp

#pragma once
#include <cstdio>
#include <string>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>


#define BACKLOG 10
#define CHECK_RET(q) if((q)==false){return -1;}
class TcpSocket
{
public:
    TcpSocket():_sockfd(-1){

    }
    //创建套接字
    bool Socket() {
        _sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(_sockfd < 0) {
            perror("socket error");
            return false;
        }
        return true;
    }
    void Addr(struct sockaddr_in *addr, const std::string &ip, const uint16_t port) {
        addr->sin_family = AF_INET;
        addr->sin_port = htons(port);
        inet_pton(AF_INET, ip.c_str(), &(addr->sin_addr.s_addr));
    }
    bool Bind(const std::string &ip, const uint16_t port) {
        struct sockaddr_in addr;
        Addr(&addr, ip, port);
        socklen_t len = sizeof(struct sockaddr_in);
        int ret = bind(_sockfd, (struct sockaddr*)&addr, len);
        if(ret < 0)
        {
            perror("bind error");
            return false;
        }
        return true;
    }
    bool Listen(int backlog = BACKLOG){
        int ret = listen(_sockfd, backlog);
        if(ret < 0){
            perror("listen error");
            return false;
        }
        return true;
    }
    bool Connect(const std::string &ip, const uint16_t port) {
        struct sockaddr_in addr;
        Addr(&addr, ip,  port);
        socklen_t len = sizeof(struct sockaddr_in);
        int ret = connect(_sockfd, (struct sockaddr*)&addr, len);
        if(ret < 0) {
            perror("connet error");
            return false;
        }
        return true;
    }
    bool Accept(TcpSocket *sock, std::string *ip = NULL, uint16_t *port = NULL){
        struct sockaddr_in addr;
        socklen_t len = sizeof(struct sockaddr_in);
        int clisockfd = accept(_sockfd, (struct sockaddr*)&addr, &len);
        if(clisockfd < 0) {
            perror("accept error");
            return false;
        }
        sock->_sockfd = clisockfd;
        if(ip != NULL) {
            *ip = inet_ntoa(addr.sin_addr);
        }
        if(port != NULL) {
            *port = ntohs(addr.sin_port);
        }
        return true;
    }
    bool Send(const std::string &data) {
        int ret = send(_sockfd, data.c_str(), data.size(), 0);
        if(ret < 0) {
            perror("send error");
            return false;
        }
        return true;
    }
    bool Recv(std::string *buf) {
        char tmp[4096] = {0};
        int ret = recv(_sockfd, tmp, 4096, 0);
        if(ret < 0) {
            perror("recv error");
            return false;
        }else if(ret == 0){
            printf("connection break\n");
            return false;
        }
        buf->assign(tmp, ret);
        return true;
    }
    bool Close() {
        close(_sockfd);
        _sockfd = -1;
    }

private:
    int _sockfd;
};

2.tcp_cli.cpp

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include "tcpSocket.hpp"

int main(int argc, char *argv[])
{
    if(argc != 3) {
        printf("em:./tcp_cli 172.17.0.1 9010 ---服务绑定的地址\n");
        return -1;
    }
    std::string ip = argv[1];
    uint16_t port = atoi(argv[2]);
    TcpSocket cli_sock;

    CHECK_RET(cli_sock.Socket());
    CHECK_RET(cli_sock.Connect(ip, port));

    while(1) {
        printf("client say:");
        fflush(stdout);
        std::string buf;
        std::cin >> buf;

       CHECK_RET(cli_sock.Send(buf));
       buf.clear();
       CHECK_RET(cli_sock.Recv(&buf));
       printf("server say: %s\n", buf.c_str());
    }
    cli_sock.Close();

    return 0;
}

3.tcp_srv.cpp

#include<iostream>
#include<stdlib.h>
#include "tcpSocket.hpp"

int main(int argc, char *argv[])
{
    if(argc != 3) {
        printf("em: ./tcp_srv 172.17.0.1 9010\n");
        return -1;
    }
    std::string ip = argv[1];
    uint16_t port = atoi(argv[2]);

    TcpSocket lst_sock;
    CHECK_RET(lst_sock.Socket());
    CHECK_RET(lst_sock.Bind(ip, port));
    CHECK_RET(lst_sock.Listen());
    while(1) {
        TcpSocket cli_sock;
        std::string cli_ip;
        uint16_t cli_port;

        bool ret = lst_sock.Accept(&cli_sock, &cli_ip, &cli_port);
        if(ret == false) {
            continue;
        }
        std::string buf;
        if(cli_sock.Recv(&buf) == false) {
            cli_sock.Close();
            continue;
        }
        printf("client:[%s:%d] say:%s\n", &cli_ip[0], cli_port, &buf[0]);
        std::cout << "server say;";
        fflush(stdout);
        buf.clear();
        std::cin >> buf;
        if(cli_sock.Send(buf) == false){
            cli_sock.Close();
            continue;
        }

    }
    lst_sock.Close();
    return 0;
}

标签:__,return,addr,int,sock,tcp,sockfd,接字
来源: https://blog.csdn.net/childemao/article/details/104897135

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有