网络——socket编程_TCP

作者:小 琛
欢迎转载,请标明出处

socket_tcp编程流程

在这里插入图片描述

为什么要新创建socket来进行通信?
在tcp通信中,往往为客户端真正服务的是新创建的出来的socket,而最初连接用的socket实际是监听作用这样做的原因是当已经有一个连接且在通信时,仍然允许新的客户端连接

在这里插入图片描述

函数接口

创建套接字的接口
int socket(int domain, int type, int protocol)
参数:
domain:地址域,传入协议的版本。针对于网络层的参数。
AF_INET:ipv4版本协议 AF_INET6: IPV6版本协议
type:套接字的类型。针对传输层的参数
SOCK_STREAM::流式套接字;协议默认tcp,不支持udp
SOCK_DGRAM::数据报套接字;默认协议为udp,不支持tcp
protocol:协议
0:采用套接字默认协议
IPPROTO_TCP(或6):tcp协议
IPPROTO_UDP(或17):udp协议
返回值:套接字的操作句柄,本质为一个文件描述符,通常称之为套接字描述符。

绑定地址信息接口
int bind (int sockfd, const struct sockaddr* addr, socklen_t addrlen)
参数:
sockfd:套接字操作句柄
addr:为更好的兼容不同协议的地址信息而设定的结构体
struct sockaddr_in
{
sin_family;//告诉内核以何种协议去解析,例如传AF_INET即ipv4
sin_port;端口信息
sin_addr.s_addr;uint32_t类型的ip地址
}
注意:我们通常使用上述结构体,但和参数类型并不匹配,因此该参数需要进行强转,否则会报错;(struct sockte_addr*)&addr。
addrlen:地址信息长度

监听:
int listen(int sockfd, int backlog )

  1. 参数:
    sockfd:套接字描述符
    backlog:已完成连接队列的大小。可以指定大小,若当前队列已满,会丢弃新来的连接,从以完成连接队列中获取创建完成的新连接
  2. 返回值:
    失败返回-1,否则返回1
    3.监听状态
    已完成连接队列:三次握手完成的连接集合
    未完成连接队列:处于三次握手当中的连接集合

获取连接
int accept (int sockfd, struct sockaddr* addr,socklen_t addrlen)

  1. 参数
    sockfd:侦听套接字描述符
    addr:客户端的地址信息
    addrlen:客户端地址信息长度
  2. 返回值
    返回新创建出来socket的sockfd,通过新创建出来的socket为客户端服务。
  3. 注意
    该接口是从已完成连接的队列中获取连接,因此当已完成队列中没有新的连接时候,会阻塞,知道获取新的连接

发送连接
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen)

  1. 参数
    sockfd:套接字描述符
    addr:服务端地址信息,需要在代码中配置
    addrlen:地址信息长度
  2. 返回值
    失败返回-1,否则为1

发送数据
sszie_t send(int sockfd, const void* buf, size_t len, int flags)

  1. 参数
    sockfd:套接字描述符,要使用accept的返回值
    buf:要发送的数据
    len:发送的数据长度
    flags:发送方式,0为阻塞发送
  2. 返回值:
    大于0:发送数据的长度
    等于0:标识对端关闭了连接
    小于0:失败

接收数据
ssize_t recv(int sockfd, void* buf, size_t len, int flags)

  1. 参数
    sockfd:套接字描述符,要使用accept的返回值
    buf:接收数据的存放
    len:最大接收长度
    flags:接收方式,0为阻塞接收,MSG_PEEK为探测接收
  2. 返回值
    大于0:发送数据的长度
    等于0:标识对端关闭了连接
    小于0:失败

关闭套接字
close(int sockfd)

tcp通信demo

  1. tcpsvr.hpp
  1 #pragma once                                                                                                                      
  2 
  3 #include <cstring>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <sys/socket.h>
  7 #include <stdlib.h>
  8 #include <iostream>
  9 #include <string>
 10 #include <netinet/in.h>
 11 #include <arpa/inet.h>
 12 
 13 class TcpSvr
 14 {
 15     public:
 16         TcpSvr()
 17         {
 18             _sockfd=-1;
 19         }
 20         ~TcpSvr()
 21         {}
 22         //1.创建套接字
 23         bool CreatSocket()
 24         {
 25             _sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 26             if (_sockfd < 0)
 27             {
 28                 perror("socket");
 29                 return false;
 30             }
 31             return true;
 32         }
 33         //2.绑定地址信息
 34         bool Bind(std::string& ip,uint16_t port)
 35         {
 36             struct sockaddr_in addr;
 37             addr.sin_family=AF_INET;
 38             addr.sin_port=htons(port);
 39             addr.sin_addr.s_addr=inet_addr(ip.c_str());
 40             int ret=bind(_sockfd,(struct sockaddr*)&addr,sizeof(addr));
 41             if (ret < 0)
 42             {
 43                 perror("bind");
 44                 return false;                                                                                                     
 45             }
 46             return true;
 47         }
 48         // 3.侦听
 49         bool Listen(int n=5)
 50         {                                                                                                                         
 51             int ret=listen(_sockfd,n);
 52             if (ret < 0)
 53             {
 54                 perror("listen");
 55                 return false;
 56             }
 57             return true;
 58         }
 59         //4.获取连接
 60         bool Accept(struct sockaddr_in* addr,TcpSvr* ts)
 61         {
 62             socklen_t socklen=sizeof(struct sockaddr_in);
 63             int serverfd=accept(_sockfd,(struct sockaddr*)addr,&socklen);
 64             if (serverfd < 0)
 65             {
 66                 perror("accept");
 67                 return false;
 68             }
 69             ts->_sockfd=serverfd;
 70             return true;
 71         }
 72         //5.发起连接
 73         bool Connect(std::string& ip,uint16_t port)
 74         {
 75             struct sockaddr_in addr;
 76             addr.sin_family=AF_INET;
 77             addr.sin_port=htons(port);
 78             addr.sin_addr.s_addr=inet_addr(ip.c_str());
 79             int ret =connect(_sockfd,(struct sockaddr*)&addr,sizeof(addr));
 80             if (ret < 0)
 81             {
 82                 perror("connect");
 83                 return false;
 84             }
 85             return true;
 86         }
 87         //6.发送数据
 88         bool Send(std::string& data)
 89         {
 90             int sendszie=send(_sockfd,data.c_str(),data.size(),0);
 91             if (sendszie < 0)
 92             {
 93                 perror("send");
 94                 return false;
 95             }
 96             return true;
 97         }
 98         //7.接收数据
 99         bool Recv(std::string* buff)
100         {
101             char buf[1024];
102             memset(buf,'\0',sizeof(buf));
103             int recvsize=recv(_sockfd,buf,sizeof(buf)-1,0);
104             if (recvsize < 0)
105             {
106                 perror("recv");
107                 return false;
108             }
109             else if (recvsize == 0)//断开连接
110             {
111                 printf("The connection has been disconnected\n");
112                 return false;
113             }                                                                                                                     
114             else
115             {
116                 (*buff).assign(buf,recvsize);
117                 return true;
118             }
119         }
120             //8.关闭
121             void Close()
122             {
123                 close(_sockfd);
124                 _sockfd=-1;
125             }
126     private:
127         int _sockfd;
128 };                    
  1. cli.cpp
  1 #include "tcpsvr.hpp"                                                                                                             
  2 
  3 int main(int argc,char* argv[])
  4 {
  5     if (argc!=3)
  6     {
  7         printf("Start Client: ./cli [server ip] [server port]\n");
  8         return 0;
  9     }
 10     std::string ip=argv[1];
 11     uint16_t port=atoi(argv[2]);
 12 
 13     TcpSvr us;
 14     if (!us.CreatSocket())
 15     {
 16         return 0;
 17     }
 18     if (!us.Connect(ip,port))
 19     {
 20         return 0;
 21     }
 22     while (1)
 23     {
 24         printf("please enter :");
 25         fflush(stdout);
 26         std::string buf;
 27         std::cin >> buf;
 28         us.Send(buf);
 29 
 30         us.Recv(&buf);
 31         printf("I get :%s\n",buf.c_str());
 32     }
 33     us.Close();
 34     return 0;
 35 }                     
  1. svr.cpp
  1 #include "tcpsvr.hpp"                                                                                                             
  2 
  3 int main(int argc,char* argv[])
  4 {
  5     if (argc != 3)
  6     {
  7         printf("Start Server: ./svr [ip] [port]\n");
  8         return 0;
  9     }
 10     std::string ip=argv[1];
 11     uint16_t port=atoi(argv[2]);
 12 
 13     TcpSvr us;
 14     if (! us.CreatSocket())
 15     {
 16         return 0;
 17     }
 18     if (! us.Bind(ip,port))
 19     {
 20         return 0;
 21     }
 22     if (! us.Listen(5))
 23     {
 24         return 0;
 25     }
 26 
 27     TcpSvr sursock;
 28     while (1)
 29     {
 30         struct sockaddr_in clientaddr;
 31         if (! us.Accept(&clientaddr,&sursock))
 32         {
 33             return 0;
 34         }
 35 
 36         std::string buff;
 37         sursock.Recv(&buff);
 38         printf("I get:%s\n",buff.c_str());
 39 
 40         printf("please enter :");
 41         fflush(stdout);
 42         std::cin>>buff;
 43         sursock.Send(buff);
 44     }
 45     us.Close();
 46     sursock.Close();
 47     return 0;
 48 }                                   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值