c语言sscanf函数的用法是什么
307
2022-08-28
linux C/C++ TCP网络通信实战
怎么样在Linux系统上通过TCP协议网络发送数据,首先先了解客户端和服务器工作的核心逻辑,如下图所示
各功能函数的介绍
socket
int socket(int domain, int type, int protocol)其中第一个参数:AF_LOCAL:表示的是本地地址,对应的是 Unix 套接字,这种情况一般用于本地 socket 通信,很多情况下也可以写成 AF_UNIX、AF_FILE;AF_INET:因特网使用的 IPv4 地址;AF_INET6:因特网使用的 IPv6 地址其中第二个参数:SOCK_STREAM: 表示的是字节流,对应 TCP;SOCK_DGRAM: 表示的是数据报,对应 UDP;SOCK_RAW: 表示的是原始套接字。其中第三个参数 : protocol 原本是用来指定通信协议的,但现在基本废弃。因为协议已经通过前面两个参数指定完成。protocol 目前一般写成 0 即可。其返回套接字fd示例:int clientfd = socket(AF_INET,SOCK_STREAM,0);
/* 描述IPV4的套接字地址格式 */struct sockaddr_in{ sa_family_t sin_family; /* 16-bit */ in_port_t sin_port; /* 端口号 16-bit*/ struct in_addr sin_addr; /* Internet address. 32-bit */ /* 这里仅仅用作占位符,不做实际用处 */ unsigned char sin_zero[8];};//其中in_addr的类型为typedef struct in_addr { union { struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { u_short s_w1,s_w2; } S_un_w; u_long S_addr; } S_un;} in_addr;//所以通常会有struct sockaddr_in name;name.sin_addr.s_addr = htonl (INADDR_ANY); // IPV4通配地址
bind
bind(int fd, void * addr, socklen_t len)
示例: struct sockaddr_in bindaddr; bindaddr.sin_family = AF_INET; //IPV4 bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); //指定端口 bindaddr.sin_port = htons(SERVER_PORT); //通配地址 INADDR_ANY 表示通配地址,如果你只想该服务器程序仅本机上可以访问,那么你 bind 函数中的地址就可以使用127.0.0.1; 如果你的服务只想被局域网内部机器访问,bind 函数的地址可以使用192.168.1.104;如果 希望这个服务可以被公网访问,你就可以使用地址0.0.0.0或 INADDR_ANY bind(listenfd, (struct sockaddr *)&bindaddr, sizeof(bindaddr))
listen
int listen (int socketfd, int backlog)第一个参数 socketdf 为套接字描述符,第二个参数 backlog,在 Linux 中表示已完成 (ESTABLISHED) 且未 accept 的队列大小,(全连接队列的大小)这个参数的大小决定了可以接收的并发数目。这个参数越大,并发数目理论上也会越大。但是参数过大也会占用过多的系统资源
accept
int accept(int listensockfd, struct sockaddr *cliaddr, socklen_t *addrlen)返回一个已连接套接字,此时TCP 三次握手,操作系统内核就为这个客户生成一个已连接套接字,让应用服务器使用这个已连接套接字和客户进行通信处理,最后通信完,关闭的是这个已连接套接字,监听的套接字依旧在监听第一个参数 listensockfd 是套接字,可以叫它为 listen 套接字,因为这就是前面通过 bind,listen 一系列操作而得到的套接字
//示例: struct sockaddr_in clientaddr; socklen_t clientaddrlen = sizeof(clientaddr); //accept函数第三个参数需要的类型 //接受客户端的连接 int clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientaddrlen );
connect
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen)第一个参数 sockfd 是连接套接字第二个、第三个参数 servaddr 和 addrlen 分别代表指向套接字地址结构的指针和该结构的大小。套接字地址结构必须含有服务器的 IP 地址和端口号 如果是 TCP 套接字,那么调用 connect 函数将激发 TCP 的三次握手过程,而且仅在连接建立成功或出错时才返回,其中出错返回可能有以下几种情况:三次握手无法建立,客户端发出的 SYN 包没有任何响应,于是返回 TIMEOUT 错误。这种情况比较常见的原因是对应的服务端 IP 写错。客户端收到了 RST(复位)回答,这时候客户端会立即返回 CONNECTION REFUSED 错误。这种情况比较常见于客户端发送连接请求时的请求端口写错,因为 RST 是 TCP 在发生错误时发送的一种 TCP 分节。产生 RST 的三个条件是:目的地为某端口的 SYN 到达,然而该端口上没有正在监听的服务器(如前所述);TCP 想取消一个已有连接;TCP 接收到一个根本不存在的连接上的分节。客户发出的 SYN 包在网络上引起了"destination unreachable",即目的不可达的错误。这种情况比较常见的原因是客户端和服务器端路由不通。
read/write recv/send
#include
TCP通信实战代码:
客户端代码:
默认向服务器端发送 hello world!
in_addr_t inet_addr(const char *cp);//inet_addr函数是将字符串转换网络主机地址(点分十进制)为网络字节序二进制值
#include 服务器端代码: #include 测试结果显示: 客户端: 服务器端:
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~