赞
踩
socket()
函数创建一个套接字,指定使用的协议族(如IPv4或IPv6)和socket类型(如流式socket)。bind()
函数将套接字与服务器的网络信息(如IP地址和端口号)进行绑定。listen()
函数将套接字设置为监听状态,准备接收客户端的连接请求。accept()
函数阻塞等待客户端的连接请求,并返回一个新的套接字用于与该客户端进行通信。recv()
和send()
函数与客户端进行数据的接收和发送。close()
函数关闭套接字,释放资源。socket()
函数创建一个套接字。connect()
函数向服务器发起连接请求,指定服务器的IP地址和端口号。send()
和recv()
函数与服务器进行数据的发送和接收。close()
函数关闭套接字,释放资源。- #include <sys/types.h>
- #include <sys/socket.h>
- int socket(int domain, int type, int protocol);
-
- 功能:
- 创建一个套接字,返回一个文件描述符
- 参数:
- domain:通信域,协议族
- AF_UNIX 本地通信
- AF_INET ipv4网络协议
- AF_INET6 ipv6网络协议
- AF_PACKET 底层接口
- type:套接字的类型
- SOCK_STREAM 流式套接字(tcp)
- SOCK_DGRAM 数据报套接字(udp)
- SOCK_RAW 原始套接字(用于链路层)
- protocol:附加协议,如果不需要,则设置为0
-
- 返回值:
- 成功:文件描述符
- 失败:‐1

案例
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <stdlib.h>
-
- int main(int argc, char const *argv[])
- {
- //通过socket函数创建一个TCP套接字
- int sockfd;
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("fail to socket");
- exit(1);
- }
-
- printf("sockfd = %d\n", sockfd);
-
- return 0;
- }

这段代码演示了如何使用C语言创建一个TCP套接字。在代码中,首先通过
socket()
函数创建了一个套接字,指定了协议族为AF_INET
(IPv4),套接字类型为SOCK_STREAM
(TCP)。如果创建失败,则会输出错误信息并退出程序。如果创建成功,则会输出套接字的文件描述符。最后,程序返回0表示正常退出。
执行结果
- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 功能:
- 给服务器发送客户端的连接请求
- 参数:
- sockfd:文件描述符,socket函数的返回值
- addr:要连接的服务器的网络信息结构体(需要自己设置)
- addrlen:add的长度
- 返回值:
- 成功:0
- 失败:-1
注意:
- #include <sys/types.h>
- #include <sys/socket.h>
- ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-
- 功能:
- 发送数据
- 参数:
- sockfd:文件描述符
-
- 客户端:
- socket函数的返回值
- 服务器:
- accept函数的返回值
-
- buf:发送的数据
- len:buf的长度
- flags:标志位
- 0 阻塞
- MSG_DONTWAIT 非阻塞
-
- 返回值:
- 成功:发送的字节数
- 失败:-1

注意: 不能用TCP协议发送0长度的数据包
- #include <sys/types.h>
-
- #include <sys/socket.h>
- ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- 功能:
- 接收数据
- 参数:
- sockfd:文件描述符
- 客户端:socket函数的返回值
- 服务器:accept函数的返回值
- buf:保存接收到的数据
- len:buf的长度
- flags:标志位
- 0 阻塞
- MSG_DONTWAIT 非阻塞
- 返回值:
- 成功:接收的字节数
- 失败:-1
- 如果发送端关闭文件描述符或者关闭进程,则recv函数会返回0

使用windows下的网络调试助手作为服务器
客户端的程序
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <string.h>
-
- #define N 128
-
- int main(int argc, char const *argv[])
- {
- if(argc < 3)
- {
- fprintf(stderr, "Usage: %s [ip] [port]\n", argv[0]);
- exit(1);
- }
-
- //第一步:创建套接字
- int sockfd;
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("fail to socket");
- exit(1);
- }
-
- //printf("sockfd = %d\n", sockfd);
-
- //第二步:发送客户端连接请求
- struct sockaddr_in serveraddr;
- socklen_t addrlen = sizeof(serveraddr);
-
- serveraddr.sin_family = AF_INET;
- serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
- serveraddr.sin_port = htons(atoi(argv[2]));
-
- if(connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) == -1)
- {
- perror("fail to connect");
- exit(1);
- }
-
- //第三步:进行通信
- //发送数据
- char buf[N] = "";
- fgets(buf, N, stdin);
- buf[strlen(buf) - 1] = '\0';
- if(send(sockfd, buf, N, 0) == -1)
- {
- perror("fail to send");
- exit(1);
- }
-
- //接收数据
- char text[N] = "";
- if(recv(sockfd, text, N, 0) == -1)
- {
- perror("fail to recv");
- exit(1);
- }
-
- printf("from server: %s\n", text);
-
- //第四步:关闭套接字文件描述符
- close(sockfd);
-
- return 0;
- }

这段代码是一个简单的TCP客户端程序。它接收两个命令行参数:服务器的IP地址和端口号。然后,程序会执行以下步骤:
- 创建一个TCP套接字。
- 使用
connect()
函数向服务器发送连接请求。- 从标准输入读取一行数据,并将其发送给服务器。
- 接收服务器返回的数据,并将其打印到标准输出。
- 关闭套接字文件描述符。
执行结果
1、具备一个可以确知的地址
2、让操作系统知道是一个服务器,而不是客户端
3、等待连接的到来 对于面向连接的TCP协议来说,连接的建立才真正意味着数据通信的开始
- #include <sys/types.h>
-
- #include <sys/socket.h>
- int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 功能:
- 将套接字与网络信息结构体绑定
- 参数:
- sockfd:文件描述符,socket的返回值
- addr:网络信息结构体
- 通用结构体(一般不用)
- struct sockaddr
- 网络信息结构体 sockaddr_in
- #include <netinet/in.h>
- struct sockaddr_in
- addrlen:
- addr的长度
- 返回值:
- 成功:0
- 失败:-1

简单写个例子
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
-
- int main() {
- // 创建一个流式套接字
- int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd == -1) {
- perror("socket");
- return -1;
- }
-
- // 初始化网络信息结构体
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(8080); // 绑定到8080端口
- addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定到任意IP地址
-
- // 将套接字与网络信息结构体绑定
- socklen_t addrlen = sizeof(addr);
- if (bind(sockfd, (struct sockaddr *)&addr, addrlen) == -1) {
- perror("bind");
- return -1;
- }
-
- printf("Bind successful\n");
-
- // 关闭套接字
- close(sockfd);
-
- return 0;
- }

在这个实例中,我们首先使用
socket()
函数
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 功能: 阻塞等待客户端的连接请求 参数: sockfd:文件描述符,socket函数的返回值 addr:接收到的客户端的信息结构体(自动填充,定义变量即可) addrlen:addr的长度 返回值: 成功:新的文件描述符(只要有客户端连接,就会产生新的文件描述符,这个新的文件描述符专门与指定的客户端进行通信的) 失败:-1创建了一个流式套接字,然后初始化了一个
sockaddr_in
结构体,将套接字绑定到8080端口和任意IP地址。最后,我们使用bind()
函数将套接字与网络信息结构体绑定,如果绑定成功,则会输出"Bind successful"。
- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- int listen(int sockfd, int backlog);
- 功能:
- 将套接字设置为被动监听状态,这样做之后就可以接收到连接请求
- 参数:
- sockfd:文件描述符,socket函数返回值
- backlog:允许通信连接的主机个数,一般设置为5、10
- 返回值:
- 成功:0
- 失败:-1
- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- 功能:
- 阻塞等待客户端的连接请求
- 参数:
- sockfd:文件描述符,socket函数的返回值
- addr:接收到的客户端的信息结构体(自动填充,定义变量即可)
- addrlen:addr的长度
- 返回值:
- 成功:新的文件描述符(只要有客户端连接,就会产生新的文件描述符,这个新的文件描述符专门与指定的客户端进行通信的)
- 失败:-1
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <string.h>
-
- #define N 128
-
- int main(int argc, char const *argv[])
- {
- if(argc < 3)
- {
- fprintf(stderr, "Usage: %s [ip] [port]\n", argv[0]);
- exit(1);
- }
-
- //第一步:创建套接字
- int sockfd;
- if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("fail to socket");
- exit(1);
- }
-
- //第二步:将套接字与服务器网络信息结构体绑定
- struct sockaddr_in serveraddr;
- socklen_t addrlen = sizeof(serveraddr);
-
- serveraddr.sin_family = AF_INET;
- serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
- serveraddr.sin_port = htons(atoi(argv[2]));
-
- if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) == -1)
- {
- perror("fail to bind");
- exit(1);
- }
-
- //第三步:将套接字设置为被动监听状态
- if(listen(sockfd, 10) == -1)
- {
- perror("fail to listen");
- exit(1);
- }
-
- //第四步:阻塞等待客户端的链接请求
- int acceptfd;
- struct sockaddr_in clientaddr;
- if((acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) == -1)
- {
- perror("fail to accept");
- exit(1);
- }
-
- //打印连接的客户端的信息
- printf("ip:%s, port:%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
-
- //第五步:进行通信
- //tcp服务器与客户端通信时,需要使用accept函数的返回值
- char buf[N] = "";
- if(recv(acceptfd, buf, N, 0) == -1)
- {
- perror("fail to recv");
- }
-
- printf("from client: %s\n", buf);
-
- strcat(buf, " *_*");
- if(send(acceptfd, buf, N, 0) == -1)
- {
- perror("fail to send");
- exit(1);
- }
-
- //关闭套接字文件描述符
- close(acceptfd);
- close(sockfd);
-
- return 0;
- }

- 创建一个TCP套接字。
- 将套接字与服务器的IP地址和端口号绑定。
- 将套接字设置为被动监听状态,等待客户端的连接请求。
- 阻塞等待客户端的连接请求,并接受连接。
- 打印连接的客户端的IP地址和端口号。
- 接收客户端发送的数据,并将其打印出来。
- 向客户端发送数据。
- 关闭与客户端的连接,并关闭套接字。
执行结果
- 使用close函数即可关闭套接字 关闭一个代表已连接套接字将导致另一端接收到一个0长度的数据包
- 做服务器时 1>关闭监听套接字将导致服务器无法接收新的连接,但不会影响已经建立的连接 2>关闭accept返回的已连接套接字将导致它所代表的连接被关闭,但不会影响服务器 的监听
- 做客户端时 关闭连接就是关闭连接,不意味着其他
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。