socket
int socket (int __domain, int __type, int __protocol);
-
__domain为协议域,又称协议族,我们最常用的有AF_INET、AF_INET6(也可以写作为PF_INET、PF_INET6),分别代表IPv4地址和IPv6地址。
-
__type为数据传输方式或套接字类型,最常见的有SOCK_STREAM和 SOCK_DGRAM,其中SOCK_STREAM为面向连接的数据传输方式,是基于TCP的协议,数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送,但效率相对较慢;而SOCK_DGRAM是无连接的数据传输方式,是基于UDP的协议,即只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。
-
__protocol为传输协议,对应上述的__type,常用的有IPPROTO_TCP 和 IPPTOTO_UDP分别代表TCP和UDP协议。而系统会根据__type的值自行选择,因此该项一般可直接指定为0。
-
socket返回的值是一个文件描述符,由于0,1,2,都被占用,所以是从3开始,错误时返回-1;
bind()和connect()函数
bind()函数用于服务器端,用来绑定套接字和自己的ip地址和端口;
connect()函数用于客户端,旨在连接套接字和服务器端的IP地址和端口。
两个函数的返回值表示是否成功(0表示成功,-1表示错误)
函数原型如下:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
-
sockfd为socket返回的文件描述符。
-
addr为一个const struct sockaddr *指针,由于兼容性的原因,这里我们只能先使用sockaddr_in 结构体来定义相应的IP地址和端口号,然后再强制转换为 sockaddr 类型的方式。
-
addrlen为2中结构体的大小,可由sizeof()计算给出。
在使用上述两个函数之前,需要先给sockaddr_in 结构体中的成员赋值,其中sockaddr_in 结构体的成员变量如下:
struct sockaddr_in{
sa_family_t sin_family; //协议族,和socket()函数中一致即可
uint16_t sin_port; //16位的端口号,尽量保证端口号在1024~65536之间
struct in_addr sin_addr; //32位IP地址
char sin_zero[8]; //不使用,一般用0填充
};
listen()和accept()函数
在服务器端,绑定了套接字后,还需通过listen()函数进入到监听状态。
监听状态下调用accept()函数进行接收,当收到来自客户端的请求后就可以建立连接了。
listen()函数返回值0表示成功,-1表示失败
int listen(int __fd, int __n);
-
__fd为socket返回的文件描述符。
-
__n为请求队列的最大长度,也即缓冲区大小。当socket正在处理客户端请求时,如果有新的请求到来,只能被放进缓冲区,这个参数就是表明能接受多少个客户端请求。
accept()函数返回一个新的文件描述符,表示和对应的客户端进行通信。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-
__fd为socket返回的文件描述符。
-
addr为一个const struct sockaddr *指针,由于兼容性的原因,这里我们只能先使用sockaddr_in 结构体来定义相应的IP地址和端口号,然后再强制转换为 sockaddr 类型的方式。
-
addrlen为一个指针,解引用后值为2中结构体的大小,可由sizeof()计算给出。
send()、recv()、read()和write()函数
send()和write()返回值为向fd写入的字节数,=0时断开连接,<0时出错。
recv()和read()返回值为从fd读取的字节数,=0时断开连接或读取结束,<0时出错。
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void*buf,size_t nbytes);
-
read:负责从描述符fd中读取内容,当读取成功时,read返回实际所读的字节数(大于0);如果返回的值为0,表示已经读到文件结束了;如果返回的值小于0,则出现错误,如果错误为EINTR,说明错误是由中断引起的,如果是ECONNREST表示网络连接出了问题。
-
write:将buf中的nbytes字节内容写入到文件描述符fd,成功时返回写的字节数,失败的时候返回-1;在实际的程序中,写入有两种可能:
- write的返回值大于0,表示写了部分或者是全部的数据。这样我们用一个while循环来不停的写入,但是循环过程中的buf参数和nbyte参数得由我们来更新。也就是说,网络写函数是不负责将全部数据写完之后在返回的。
- 返回的值小于0,此时出现了错误。我们要根据错误类型来处理.如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接).
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
第四个参数可以是文章来源:https://www.toymoban.com/news/detail-426072.html
flags | 描述 |
---|---|
MSG_DONTROUTE | 不查找表 |
MSG_OOB | 接受或者发送带外数据 |
MSG_PEEK | 查看数据,并不从系统缓冲区移走数据 |
MSG_WAITALL | 等待所有数据 |
当recv/send的flag参数设置为0时,则和read/write是一样的。
如果有如下几种需求,则read/write无法满足,必须使用recv/send:文章来源地址https://www.toymoban.com/news/detail-426072.html
- 为接收和发送进行一些选项设置
- 从多个客户端中接收报文
- 发送带外数据(out-of-band data)
TCP客户端
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<netdb.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
using namespace std
到了这里,关于c++ socket、 listen、accept、recv 、send、 connect函数记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!