欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > Linux高阶——1116—SOCKET套接字基础

Linux高阶——1116—SOCKET套接字基础

2025/5/2 2:26:49 来源:https://blog.csdn.net/weixin_74681777/article/details/143829182  浏览:    关键词:Linux高阶——1116—SOCKET套接字基础

1、SOCKET套接字基础

操作系统提供,用于开发网络应用的一系列API函数,我们称之为套接字函数

套接字函数适用于各个语言和平台,除了API可以不同,其他概念理论或流程逻辑都相同

1、在Linux操作系统中,sock为整型,也称int sockfd,sock描述符,后续网络通信都是用此描述符

2、int sockfd,包含网络信息,默认下包含默认地址0.0.0.0与随机端口,因此sockfd创建后可以立即使用

3、int sockfd,套接字描述符,后续用于数据传输,recv(int sock),send(sockfd),sendto(sockfd),recvfrom(sockfd)

4、struct socksddr_in网络信息结构体

2、socket函数

1、socket()——socket创建

int sockfd=socket(AF_INET|AF_INET6,SOCK_STREAM|SOCK_DGRAM,0);

第一个参数——指定使用的socket协议

第二个参数——传输层协议,TCP或UDP

返回值——成功返回整型的(大于0的)socket,失败返回-1

当刚创建时,socket包含的ip为本机任意ip,包含的端口号为随机端口号,因此刚创建出来时就可以使用

因此客户端的sockfd创建以后,无需绑定,也可以使用,因为里面含有本机任意ip和端口号

2、bind()——socket绑定

int value=bind(int sockfd,struct sockaddr* addr,socklen_t addrlen);
bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));

第一个参数——int类型的socket

第二个参数——网络信息结构体的地址

第三个参数——网络信息结构体的长度

返回值——成功返回0,不成功返回-1

sockfd里可以自定义网络信息(指定ip和port),使用bind对int sockfd中的网络信息进行设置自定义

固定信息,一般只有服务端需要,大多数服务端必须绑定,保证客户端能够找到服务端,客户端随意

大多数时间udp都需要bind,而tcp只有服务端需要绑定

3、listen()——监听网络连接状态

listen(int sockfd,int backlog=128);

第一个参数——需要监听的socket

第二个参数——监听序列

返回值——成功返回0,不成功返回-1

监听连接状态,一般只有TCP协议使用

TCPIP协议的后台有双队列,第一个队列存储的为等待三次握手的socket,第二个队列存储握手成功的socket

等待三次握手的队列不能过短:因为如果等待握手的socket的数量超过了等待握手队列的长度,则下个将要等待连接的socket会被服务器主机将RST置0(复位:让客户端重连,如果客户端不重连,连接将会丢失)

队列不能过长:浪费内存资源

定位128的队列长度可以保证过万的连接

4、accept()——执行此函数等待连接,并完成握手(服务端使用)

如果存在一个服务端,有20000个客户端连接此服务端,此时服务器软件内存在多少个socket?

答:存在20001个,存在1个socket是专门用于请求连接的,其余20000个均为连接成功后,客户端的用于传输数据的socket

用于连接的socket

int socket_sock;

用于传输的socket——计算进程sock最大值,sock最大值=连接数量+1

int client_sock;

accept是经典的阻塞连接函数

client_sock=accept(server_sock,struct sockaddr* client_addr,&addrlen);

第一个参数——服务端socket

第二个参数——客户端连接成功,成功后将客户端的网络信息结构体传出到client_addr中,获得客户端的ip和端口号

第三个参数——传入传出信息长度,传入能够接收的长度,传出结构体实际接收到多大的长度

socklen_t addrlen;
addrlen=sizeof(client_addr);

需要注意:每次连接前都要初始化addrlen,否则能够输入的大小会越来越小

返回值——指向客户端的socket——client_sock

client_sock存储指向客户端的sock,后续与客户端数据通信使用它

5、connect()——通过此函数对目标请求tcp连接(客户端使用)

connect(int sockfd,struct sockaddr* destaddr,sizeof(destaddr));

第一个参数——连接的socket(客户端只有一个socket)

第二个参数——目标信息结构体

第三个参数——目标信息结构体的长度

阻塞请求连接,成功返回0,失败返回-1

6、recv()读取指定sockfd中的数据包

ssize_t wlen=send(int sockfd,void* buf,strlen(buf),MSG_NOSIGNAL);

第一个参数——发送目标的sockfd

第二个参数——数据buf

第三个参数——数据长度size

第四个参数——选项

返回值——发送的长度

7、send()向sockfd发送数据包

ssize_t rlen=recv(int sockfd,void* buf,size(buf),MSG_DONTWAIT);

第一个参数——发送的人的sockfd

第二个参数——数据buf

第三个参数——数据长度size

第四个参数——选项flags=0—阻塞读,MSG_DONTWAIT—非阻塞读

返回值——发送的长度

3、客户端代码

#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>int main()
{struct sockaddr_in server_addr;bzero(&server_addr,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8080);server_addr.sin_addr.s_addr = inet_addr("82.157.31.74");int client_sock;if((client_sock=socket(AF_INET,SOCK_STREAM,0))==-1){   perror("sock create failed");return -1; }   socklen_t addrlen;printf("TCP IO Client Running...\n");addrlen = sizeof(server_addr);if((connect(client_sock, (struct sockaddr*)&server_addr, addrlen))==-1){   perror("failed");close(client_sock);return -1; }   char buffer[1024];recv(client_sock, buffer, sizeof(buffer), 0); printf("Received from server: %s\n", buffer);close(client_sock);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词