C++学习之Socket
Socket是什么
socket就是套接字的意思,用于描述地址和端口。应用程序通过socket向网络发出请求或者回应。
socket编程有三种:
- 流式套接字(SOCK_STREAM)
- 数据报套接字(SOCK_DGRAM)
- 原始套接字(SOCK_RAW)
前两者较常用。基于TCP的socket编程是流式套接字。
服务端和客户端都做了什么
服务端:
建立socket,声明自身的port和IP,并绑定到socket,使用listen监听,然后不断用accept去查看是否有连接。如果有,捕获socket,并通过recv获取消息的内容,通信完成后调用closeSocket关闭这个对应accept到的socket。如果不需要等待任何客户端连接,那么用closeSocket直接关闭自身的socket。
转载至:https://blog.csdn.net/zahngjialiang/article/details/53929584
客户端:
建立socket,通过端口号和地址确定目标服务器,使用Connect连接到服务器,send发送消息,等待处理,通信完成后调用closeSocket关闭socket。
三次握手四次挥手是什么
第一次握手:Client将SYN(同步序列编号Synchronize Sequence Numbers)置1,随机产生一个初始序列号seq发送给Server,进入SYN_SENT状态;
第二次握手:Server收到Client的SYN=1之后,知道客户端请求建立连接,将自己的SYN置1,ACK(确认字符Acknowledge Character)置1,产生一个acknowledge number=sequence number+1,并随机产生一个自己的初始序列号,发送给客户端;进入SYN_RCVD状态;
第三次握手:客户端检查acknowledge number是否为序列号+1,ACK是否为1,检查正确之后将自己的ACK置为1,产生一个acknowledge number=服务器发的序列号+1,发送给服务器;进入ESTABLISHED状态;服务器检查ACK为1和acknowledge number为序列号+1之后,也进入ESTABLISHED状态;完成三次握手,连接建立。
第一次挥手:Client将FIN(finish)置为1,发送一个序列号seq给Server;进入FIN_WAIT_1状态;
第二次挥手:Server收到FIN之后,发送一个ACK=1,acknowledge number=收到的序列号+1;进入CLOSE_WAIT状态。此时客户端已经没有要发送的数据了,但仍可以接受服务器发来的数据。
第三次挥手:Server将FIN置1,发送一个序列号给Client;进入LAST_ACK状态;
第四次挥手:Client收到服务器的FIN后,进入TIME_WAIT状态;接着将ACK置1,发送一个acknowledge number=序列号+1给服务器;服务器收到后,确认acknowledge number后,变为CLOSED状态,不再向客户端发送数据。客户端等待2*MSL(报文段最长寿命)时间后,也进入CLOSED状态。完成四次挥手。
—————————————————————————————
原文链接:https://blog.csdn.net/weixin_41969690/article/details/106196702
Windows下的代码怎么写,参考:
https://blog.csdn.net/zahngjialiang/article/details/53929584
对于函数解释的很清晰。
另外目前的教程都是有服务端和客户端的代码的,刚开始看真的很蒙,不明白要怎么运行。其实他们是把两个代码分别编译成EXE后进行测试的。其实我们可以下载一个TCP调试助手,就可以只写一端的代码进行测试了。比如下图这个:
Socket代码解析
1. WSAStartup函数
使用Socket之前必须调用WSAStartup函数,此函数在应用程序中用来初始化Windows Sockets DLL,只有此函数调用成功后,应用程序才可以调用Windows SocketsDLL中的其他API函数,否则后面的任何函数都将调用失败。
函数的原型:
int WSAAPI WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData
);
函数的使用:
WSAStartup(MAKEWORD(2, 2), &wsaData);//第一个参数是dll版本号,第二个参数是创建的socket对象
2. WSADATA
WSADATA,一种数据结构。
这个结构被用来存储被WSAStartup函数调用后返回的Windows Sockets数据。
3. MAKEWORD函数
Windows Sockets DLL期望调用者使用的Windows Sockets规范的版本。 高位字节存储副版本号, 低位字节存储主版本号,可以用WORD MAKEWORD(BYTE,BYTE ) 返回这个值,例如:MAKEWORD(1,1)
前面都做完了之后:
//需要确认是否初始化成功if (WSAStartup(sockVersion, &wsdata) != 0){return 1;}
4. SOCKET函数
SOCKET socket(int af,int type,int protocol);
af:一个地址家族,通常为AF_INET(AF–ADDRESS FAMILY)
type:套接字类型,SOCK_STREAM表示创建面向流连接的套接字。为SOCK_DGRAM,表示创建面向无连接的数据包套接字。为SOCK_RAW,表示创建原始套接字
protocol:套接字所用协议,不指定可以设置为0 返回值就是一个socket
函数的使用:
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (serverSocket == INVALID_SOCKET){cout << "Socket error" << endl;return 1;}
5. sockaddr_in 结构体
成员变量如下:
struct sockaddr_in{sa_family_t sin_family; //地址族(Address Family),也就是地址类型uint16_t sin_port; //16位的端口号struct in_addr sin_addr; //32位IP地址char sin_zero[8]; //不使用,一般用0填充
};
sin_family 和 socket() 的第一个参数的含义相同,取值也要保持一致。
sin_prot 为端口号。uint16_t 的长度为两个字节,理论上端口号的取值范围为 0~65536,但 0~1023
的端口一般由系统分配给特定的服务程序,例如 Web 服务的端口号为 80,FTP 服务的端口号为 21,所以我们的程序要尽量在
1024~65536 之间分配端口号。 端口号需要用 htons() 函数转换,后面会讲解为什么。sin_addr 是 struct in_addr 结构体类型的变量,下面会详细讲解。
sin_zero[8] 是多余的8个字节,没有用,一般使用 memset() 函数填充为 0。上面的代码中,先用 memset()
将结构体的全部字节填充为 0,再给前3个成员赋值,剩下的 sin_zero 自然就是 0 了。
6. memset函数
复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
void *memset(void *str, int c, size_t n)
函数的使用:
sockaddr_in sockAddr;//创建套接字地址memset(&sockAddr, 0, sizeof(sockAddr));//用0填充每个字节sockAddr.sin_family = PF_INET;//使用PF_INET地址族,也就是IPv4sockAddr.sin_addr.s_addr = inet_addr("192.168.1.200");//具体的地址sockAddr.sin_port = htons(4196);//端口
7. in_addr 结构体(sin_addr)
sockaddr_in 的第3个成员是 in_addr 类型的结构体,该结构体只包含一个成员:
struct in_addr{in_addr_t s_addr; //32位的IP地址
};
in_addr_t
在头文件 <netinet/in.h> 中定义,等价于 unsigned long
,长度为4个字节。也就是说,s_addr
是一个整数,而IP地址是一个字符串,所以需要 inet_addr() 函数
进行转换。
8. bind()函数
函数声明:
int bind(SOCKET sock, const struct sockaddr *addr, int addrlen);
sock 为 socket 文件描述符,addr 为 sockaddr 结构体变量的指针,addrlen 为 addr 变量的大小,可由 sizeof() 计算得出。
函数的使用:
bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
或者用下面的代码:
if (bind(serverSocket, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {cout << "Bind error" << endl;return 1;}
9.listen()函数
函数原型为:
int listen(SOCKET sock, int backlog);
sock 为需要进入监听状态的套接字,backlog 为请求队列的最大长度。
该函数只有服务端有,客户端没有
函数的使用:
if (listen(serverSocket, 10) == SOCKET_ERROR) {cout << "Listen error" << endl;return 1;}
10.accept()函数
函数的原型:
int accept(int s, struct sockaddr * addr, int * addrlen);
函数说明:
accept()用来接受参数s 的socket 连线. 参数s 的socket 必需先经bind()、listen()函数处理过,
当有连线进来时accept()会返回一个新的socket 处理代码, 往后的数据传送与读取就是经由新的socket处理, 而原来参数s
的socket 能继续使用accept()来接受新的连线要求. 连线成功时, 参数addr 所指的结构会被系统填入远程主机的地址数据,
参数addrlen 为scokaddr 的结构长度
函数的使用:
SOCKET clientSocket;sockaddr_in client_sin;int len = sizeof(client_sin);clientSocket = accept(serverSocket, (sockaddr*)&client_sin, &len);
11.send()函数
函数的原型:
int send(SOCKET s, const char *buf, int len, int flags);
send()用来将数据由指定的socket 传给对方主机. 参数s 为已建立好连接的socket. 参数msg 指向欲连线的数据内容, 参数len 则为数据长度. 参数flags 一般设0
11.closesocket()函数
函数的原型:
int closesocket(SOCKET s)
关闭套接字,释放与套接字关联的所有资源
函数的使用:
closesocket(clientSocket);
closesocket(serverSocket);
12.WSACleanup()函数
终止使用WinSock,释放为应用程序分配的相关资源
C++学习之Socket相关推荐
- python中socket模块常用吗_python网络学习笔记——socket模块使用记录
此文章记录了笔者学习python网络中socket模块的笔记. 建议初次学习socket的读者先读一遍socket模块主要函数的介绍. socket模块的介绍可以参考笔者的前一篇关于socket官方文 ...
- iOS学习之Socket使用简明教程- AsyncSocket
2019独角兽企业重金招聘Python工程师标准>>> 如果需要在项目中像QQ微信一样做到即时通讯,必须使用socket通讯,本人也是刚学习,分享一下,有什么不对的地方希望大家指正 ...
- 【Linux网络编程学习】socket API(socket、bind、listen、accept、connect)及简单应用
此为牛客Linux C++课程和黑马Linux系统编程笔记. 1. 什么是socket 所谓 socket(套接字),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象. 一个套接字就是网络 ...
- 深入学习linux socket编程之select
很多天之前都说学习关于select和poll的知识了,但是由于既要工作,又要准备论文.都忙不过来,今天终于能抽出一天的时间把select的相关知识和程序给实现了一遍. select系统调用是用来让我们 ...
- c#学习之Socket网络编程
我是新手以前没写过博客 希望大家勿喷, 在编写Socket的时候需要导入System.Net.Socket 命名空间.利用该类我们可以直接编写Socket的客户端和服务的的程序了, 这里我们只讲tpc ...
- Linux学习之----socket网络编程基础
分层模型 OSI七层模型 1.物理层:主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的地后再转 ...
- Linux学习之socket编程(一)
socket编程 socket的概念: 在TCP/IP协议中,"IP地址+TCP或UDP端口号"唯一标识网络通讯中的一个进程,"IP地址+端口号"就称为sock ...
- 菜猪的JAVA 网络编程学习之Socket用法详解(上)
在客户/服务器通信模式中,客户端需要主动创建与服务器连接的Socket(套接字),服务器端收到了客户端的连接请求,也会创建与客户连接的Socket.Socket可以看做是通信连接两端的收发器,服务器与 ...
- Python 学习笔记 - socket(基本原理和流程)
在学Python之前,先复习一下网络的基本概念. 比如TCP/IP 4层模型,最上面的应用软件发送数据包,数据包在运输层加上TCP或者UDP的报头,然后在网络层加上IP的报头,然后在数据链路层根据et ...
- android 全局 socket,学习Android socket通信之如何解决中文乱码
socket是网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄 ...
最新文章
- 机器学习基础-集成学习-13
- logistic 回归_具有Logistic回归的优秀初学者项目
- redission java_Java注解如何基于Redission实现分布式锁
- Notepad++ 经常使用快捷键 (MEMO)
- 想学web前端啊?初学者必看,HTML入门指南
- latch.await java有什么作用,Android系统。 Countdownlatch.await不起作用
- Spring day03笔记
- iSlide2022免费PPT插件(包含众多PPT模板/素材)
- python下载电影天堂_python电影天堂
- c++ 链表快速查找
- python中grid是什么意思_python中网格Grid和列表List的认识
- oracle清楚表空间碎片,ORACLE表空间的碎片整理
- ReadyBoost 的应用教程
- strcpy函数在c语言的作用是什么,strcpy函数的作用是什么呀?
- 创建vue-ssr项目
- 高性能Golang研讨会【精】
- 视觉培训2 机器学习基础知识学习
- systeminfo卡死一例分析
- C语言中strchr和strrchr函数及用法
- Connor学Android - JNI和NDK编程
热门文章
- ViewPager动画
- 纪伯伦的《我曾七次鄙视自己的灵魂》
- C语言中 sizeof(数组名) 和 strlen(数组名) 的意义
- 轻松入门进阶Flink第一课 Flink基础
- android 修改手机系统,【教程贴丨09-29】手机系统APK自己来修改
- 一种基于深度卷积神经网络(DCNN)用于于头发和面部皮肤实时分割方法
- c语言 指针漂移,C语言实例8
- PHP操作字符串 截取指定长度字符 移除字符串两侧 左侧 右侧指定字符 或空白字符 替换字符...
- 30岁转行新媒体运营晚不晚?当然不
- 高精度隧道施工人员定位安全管理解决方案