- 使用UDP实现本地通信
- socket
- 本地通信使用的信息结构体
- UDP本地通信流程
- 代码实现
- 服务器---01server.c
- 客户端---02client.c
- 执行结果
- 注意
#include本地通信使用的信息结构体int socket(int domain, int type, int protocol); 参数: domain:用于指定通信领域 AF_UNIX, AF_LOCAL 本地通信使用 type:指定套接字类型 SOCK_DGRAM UDP协议 protocol:附加协议 如果type使用的是 SOCK_STREAM 或者 SOCK_DGRAM 此时该参数可以指定为 0 返回值: 成功 文件描述符 失败 -1
struct sockaddr_un {
sa_family_t sun_family;
char sun_path[108];
};
UDP本地通信流程sun_path[108] 文件名,执行会自动创建 套节字文件
服务器: 创建套接字 socket( ) 填充服务器本地信息结构体 sockaddr_un 将套接字与服务器本地信息结构体绑定 bind( ) 进行通信 recvfrom( ) / sendto( ) 客户端: 创建套接字 socket( ) 填充客户端本地信息结构体 sockaddr_un 将套接字与客户端本地信息结构体绑定 bind() //客户端执行绑定,是为了服务器能获取客户端的信息;如果不绑定 服务器没法回复应答 填充服务器本地信息结构体 sockaddr_un 进行通信 sendto( ) / recvfrom( )代码实现 服务器—01server.c
#include客户端—02client.c#include #include #include #include #include #include #include #include #include #include #define ERRLOG(errmsg) do { printf("%s--%s(%d):", __FILE__, __func__, __LINE__); perror(errmsg); exit(-1); } while (0) //创建套接字-填充服务器网络信息结构体-绑定 int socket_bind(const char *argv[]); int main(int argc, const char *argv[]) { //创建套接字-填充服务器网络信息结构体-绑定 int sockfd = socket_bind(argv); //用来保存客户端信息的结构体 struct sockaddr_un client_addr; memset(&client_addr, 0, sizeof(client_addr)); socklen_t client_addr_len = sizeof(client_addr); //通信 char buff[128] = {0}; while (1) { //接收应答 if (-1 == recvfrom(sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&client_addr, &client_addr_len)) ERRLOG("recv error"); printf("客户端 (%s) 发来数据:[%s]n", client_addr.sun_path, buff); //组装回复给客户端的应答 strcat(buff, "---996"); //发送数据 if (-1 == sendto(sockfd, buff, sizeof(buff), 0, (struct sockaddr *)&client_addr, client_addr_len)) ERRLOG("send error"); } //关闭监听套接字 一般不关闭 close(sockfd); return 0; } //创建套接字-填充服务器网络信息结构体-绑定 int socket_bind(const char *argv[]) { // 1.创建套接字 /本地通信 /UDP int sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); if (-1 == sockfd) ERRLOG("socket error"); // 2.填充 服务器 网络信息结构体 struct sockaddr_un server_addr; memset(&server_addr, 0, sizeof(server_addr));//清空 server_addr.sun_family = AF_UNIX; //本地通信 strcpy(server_addr.sun_path, "./my_local"); //套节字文件 //结构体长度 socklen_t server_addr_len = sizeof(server_addr); // 3.将套接字和网络信息结构体绑定 if (-1 == bind(sockfd, (struct sockaddr *)&server_addr, server_addr_len)) ERRLOG("bind error"); return sockfd; }
#include执行结果#include #include #include #include #include #include #include #include #include #include #define ERRLOG(errmsg) do { printf("%s--%s(%d):", __FILE__, __func__, __LINE__); perror(errmsg); exit(-1); } while (0) //创建套接字-填充服务器网络信息结构体-绑定 int socket_bind(const char *argv[]); int main(int argc, const char *argv[]) { //创建套接字-填充服务器网络信息结构体-绑定 int sockfd = socket_bind(argv); // 填充 服务器信息 信息结构体 struct sockaddr_un server_addr; memset(&server_addr, 0, sizeof(server_addr));//清空 server_addr.sun_family = AF_UNIX; //本地通信 strcpy(server_addr.sun_path, "./my_local"); //套节字文件 //结构体长度 socklen_t server_addr_len = sizeof(server_addr); //通信 char buff[128] = {0}; while (1) { printf("请输入 : "); fgets(buff,sizeof(buff), stdin); buff[strlen(buff) - 1] = ' '; //清除 n //发送数据 if (-1 == sendto(sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&server_addr, server_addr_len)) ERRLOG("send error"); //接收应答 if (-1 == recvfrom(sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&server_addr, &server_addr_len)) ERRLOG("recv error"); printf("服务器应答[%s]n", buff); } //关闭监听套接字 一般不关闭 close(sockfd); return 0; } //创建套接字-填充服务器网络信息结构体-绑定 int socket_bind(const char *argv[]) { // 1.创建套接字 /本地通信 /UDP int sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); if (-1 == sockfd) ERRLOG("socket error"); //2.填充 客户端自己 网络信息结构体 struct sockaddr_un client_addr; memset(&client_addr, 0, sizeof(client_addr)); //清空 client_addr.sun_family = AF_UNIX; //本地通信 strcpy(client_addr.sun_path, "./my_local_cli");//套节字文件 socklen_t client_addr_len = sizeof(client_addr); // 3.将套接字和本地信息结构体绑定 if (-1 == bind(sockfd, (struct sockaddr *)&client_addr, client_addr_len)) ERRLOG("bind error"); return sockfd; }
1. 客户端侧,不仅 要将 自己的信息 结构体 与 sockfd套接字 绑定 ;还得 填充 服务器信息 信息结构体
填充 服务器信息 信息结构体 :以便于发送数据
sendto (sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&server_addr, server_addr_len))
2. 报错 :bind error: Address already in use
因为已经执行一次 套节字文件 已经存在
所以 只需要删除 套节字文件 即可



