当前位置: 首页 > news >正文

socket套接字

1.IP地址

IP地址是在IP协议中, 用来标识网络中不同主机的地址。由点分十进制组成,在数据传输中IP地址是一直不变的。

在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址和目的IP地址。

2.端口号

由2字节16位整数组成,标识当前主机的唯一进程。与进程的pid有类似作用,但端口号是专用进行网络通信。

注意:一个端口号和一个进程相关联,一个进程可以和多个端口号相关联。

传输层协议(TCP和UDP)的数据段中有两个端口号, 分别叫做源端口号和目的端口号,就是在描述 "数据是谁发的, 要 发给谁"。

3.TCP和UDP协议

这里简单说一下,TCP(Transmission Control Protocol 传输控制协议)和UDP(User Datagram Protocol 用户数据报协议)协议都是传输层协议。TCP是有连接的,面向字节流的可靠传输;UDP是无连接,面向数据报的不可靠传输。

4.网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分。但在网络中发送数据不论发送方的主机是大端机还是小端机,都要将数据转换为大端才能发送数据到网络数据流,而接收方也必须按照大端的接受方式收取数据,不论接收方是大端机还是小端机。

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

#include<arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htonl(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohl(uint16_t hostshort);
//h表示host,n表示network,l表示32位长整数,s表示16位短整数
//例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送

5.socket及其接口

Socket,全称“套接字”,是一种编程接口,主要用于网络应用程序之间进行通信。它是由操作系统提供的API(Application Programming Interface),使得程序能够创建、连接、监听网络端口并进行数据交换。在计算机网络中,每一个通信都是通过两个独立的套接字进行的,一个是客户端的套接字,另一个是服务器的套接字。在TCP/TCP/IP协议的四层模型中,它是第四层即传输层的应用接口。

socket常见API:

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器)      
int bind(int socket, const struct sockaddr *address,socklen_t address_len);// 开始监听socket (TCP, 服务器)int listen(int socket, int backlog);// 接收请求 (TCP, 服务器)int accept(int socket, struct sockaddr* address,socklen_t* address_len);// 建立连接 (TCP, 客户端)int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

domain:指定通信域,常用有:AF_UNIX/AF_LOCAL(unix7),AF_INET(ipv4),AF_INET6(ipv6/7)。

type:指定套接字类型即使用TCP/UDP协议,SCOCK_STREAM(TCP)/SOCK_DGRAM(UDP)。

sockaddr:规定不同的软件/系统使用网络接口统一数据传输的类型。sockaddr有两个子类:sockadd_in(AF_INET),sockadd_un(AF_UNIX)。

下面是一个tcp服务器实例:

#pragma once#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cstdarg>
#include <fstream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>using namespace std;class tcpserve
{
public:tcpserve(uint16_t _port) :port(_port),isrunning(false){}void Init(){listensock=socket(AF_INET,SOCK_STREAM,0);if(listensock<0){cout<<"socket errr,"<<errno<<":"<<strerror(errno)<<endl;exit(-1);}struct sockaddr_in local;bzero(&local,sizeof(local));local.sin_family=AF_INET;local.sin_port=htons(port);local.sin_addr.s_addr=htonl(INADDR_ANY);//特殊的ip可以接受所有网络接口的请求int n=bind(listensock,(struct sockaddr*)&local,sizeof(local));if(n!=0){cout<<"bind errr,"<<errno<<":"<<strerror(errno)<<endl;exit(-2);}cout<<"bind success,listensock"<<listensock<<endl;//tcp特有的,设置监听状态n=listen(listensock,1);if(n!=0){cout<<"listen errr,"<<errno<<":"<<strerror(errno)<<endl;exit(-3);}cout<<"listen success,listensock"<<listensock<<endl;}void Serve(int sockfd){char buffer[1024];while(true){ssize_t n=read(sockfd,buffer,sizeof(buffer)-1);if(n>0){buffer[n]=0;cout<<"client say#"<<buffer<<endl;string message="serve echo#";message+=buffer;write(sockfd,message.c_str(),message.size());}else if(n==0){cout<<"client quit..."<<endl;break;}else if(n<0){cout<<"read errno,errno code:"<<errno<<"errno string:"<<strerror(errno)<<endl;break;}}}void Start(){isrunning=true;while(isrunning){struct sockaddr_in peer;socklen_t len=sizeof(peer);int n=accept(listensock,(struct sockaddr*)(&peer),&len);if(n<0){cout<<"accept errno,errno code:"<<errno<<"errno string:"<<strerror(errno)<<endl;continue;}cout<<"accept success,get a new sockfd:"<<n<<endl;Serve(n);}}~tcpserve(){}
private:uint16_t port;int listensock;bool isrunning;
};

下面是一个tcp客户端:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;int main(int argc,char *argv[])
{if(argc!=3){cout<<"请输入正确的命令"<<endl;return 1;}string ip=argv[1];uint16_t port=stoi(argv[2]);int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){cout<<"socket errr,"<<errno<<":"<<strerror(errno)<<endl;return -1;}cout<<"socket success,sockfd"<<sockfd<<":"<<ip<<endl;struct sockaddr_in local;bzero(&local,sizeof(local));local.sin_family=AF_INET;local.sin_port=htons(port);local.sin_addr.s_addr=inet_addr(ip.c_str());//建立连接int n=connect(sockfd,(struct sockaddr*)&local,sizeof(local));if(n<0){cout<<"connect errr,"<<errno<<":"<<strerror(errno)<<endl;return -2; }while(true){string message;cout<<"Please Enter#";getline(cin,message);n=write(sockfd,message.c_str(),message.size());if(n>0){char buffer[1024];ssize_t m=read(sockfd,buffer,sizeof(buffer)-1);if(m>0){buffer[m]=0;cout<<"get a echo message:"<<buffer<<endl;}else break;}else break;}
}


http://www.mrgr.cn/news/57169.html

相关文章:

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”
  • Redis持久化机制RDB持久化和AOF持久化
  • 关于容器docker使用基本命令
  • 系统架构风格
  • 目标检测——yolov5-3.1的环境搭建和运行
  • MYSQL-多表查询
  • Spring Cloud --- Sentinel 授权规则
  • 入门介绍(一):脉冲神经网络(SNN)
  • Python 实现 excel 数据过滤
  • Java学习教程,从入门到精通,Java 基本数据类型(7)
  • 鸿蒙应用的Tabs 组件怎么使用
  • c++的头文件到底应该怎么写?
  • 【编程语言】Kotlin快速入门 - 高阶函数与运算符重载
  • 均匀随机掉落算法
  • 梦开始的地方 -- 两数求和
  • c++查看运行时类型
  • Thread类
  • react优化
  • Napkins:开源 AI 开发工具,实现截图或线框图到网页应用的快速转换
  • konva不透明度,查找,显示,隐藏
  • vTESTstudio系列14--vTESTstudio中自定义函数介绍1
  • RHCE时间服务器
  • Vscode + EIDE +CortexDebug 调试Stm32(记录)
  • Kamailio 网络拓扑案例分享
  • C++ set和map的模拟实现
  • Llama Tutor:开源 AI 个性化学习平台,根据主题自动制定学习计划