Linux本地socket通信--AF_UNIX
2015-12-05 11:14
519 查看
我们熟知的sockek通信一般都是基于IP的,最近见到了本机客户端与服务端通信的方法(虽然lo地址也可以本机通信),写了一些程序做实验,主要实现客户端和服务端套接字的连接、各自创建收发线程进行通信。由于功能没有优化,纠结了很久才贴上来,重点是AF_UNIX的功能已经实现了。其实AF_UNIX和AF_INET交互的流程是一样的,只不过创建套接字的宏不一样,以及数据结构的填充不一样。这种机制对Linux C编程模块化非常有用,尤其是两个进程间通信。
1、AF_UNIX对应的结构体。
struct socketaddr_un
{
_SOCKADDR_COMMON(sun_); // __SOCKADDR_COMMON(sun_) 宏定义对应的定义为 sa_family_t sun_family
char sun_path[108];
};
struct sockaddr_un是UNIX环境下套接字的地址形式,一般情况下,需要把sockaddr_un结构强制转换成sockaddr结构再传入系统调用函数中。
2、客户端代码。
3、服务端代码。
4、测试结果。
略(功能可以保证已经实现,公司网络不能上传图片,&…#*%&*…(@¥…&)。
1、AF_UNIX对应的结构体。
struct socketaddr_un
{
_SOCKADDR_COMMON(sun_); // __SOCKADDR_COMMON(sun_) 宏定义对应的定义为 sa_family_t sun_family
char sun_path[108];
};
struct sockaddr_un是UNIX环境下套接字的地址形式,一般情况下,需要把sockaddr_un结构强制转换成sockaddr结构再传入系统调用函数中。
2、客户端代码。
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> #define SERVER_SOCK_PATH "server_socket" void *send_data(void *param); void *recv_data(void *param); int main(int argc, char *argv[]) { struct sockaddr_un address; int sockfd; int len; int i, bytes; int result; pthread_t send_id, recv_id; sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (-1 == sockfd) { perror("socket"); exit(-1); } address.sun_family = AF_UNIX; strcpy(address.sun_path, SERVER_SOCK_PATH); len = sizeof(address); result = connect(sockfd, (struct sockaddr *)&address, len); if (-1 == result) { perror("connect"); close(sockfd); exit(-1); } pthread_create(&send_id, NULL, send_data, &sockfd); pthread_create(&recv_id, NULL, recv_data, &sockfd); pthread_join(send_id,NULL); pthread_join(recv_id,NULL); close(sockfd); return 0; } void *send_data(void *param) { int sock = 0; int ret = 0; int send_len = 0; fd_set sendfd; struct timeval timeout={1,0}; char string_send[128] = {0}; sock = *(int *)param; while(1) { printf("Please enter string to send:\r\n"); memset(string_send, 0, sizeof(string_send)); scanf("%s", string_send); FD_ZERO(&sendfd); FD_SET(sock, &sendfd); ret = select(sock + 1, NULL, &sendfd, NULL, &timeout); if (ret <= 0) { continue; } if (FD_ISSET(sock, &sendfd)) { send_len = send(sock, string_send, strlen(string_send), 0); if (strlen(string_send) != send_len) { printf("send string fail!\r\n"); continue; } } } return; } void *recv_data(void *param) { int sock = 0; int ret = 0; int recv_len = 0; fd_set recvfd; struct timeval timeout={1,0}; char string_recv[128] = {0}; sock = *(int *)param; while(1) { FD_ZERO(&recvfd); FD_SET(sock, &recvfd); ret = select(sock + 1, &recvfd, NULL, NULL, &timeout); if (ret <= 0) { continue; } if (FD_ISSET(sock, &recvfd)) { recv_len = recv(sock, string_recv, sizeof(string_recv), 0); if (recv_len <= 0) { printf("recv string fail!\r\n"); continue; } printf("recv string:%s\r\n", string_recv); } } return; }
3、服务端代码。
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #define SERVER_SOCK_PATH "server_socket" void *send_data(void *param); void *recv_data(void *param); int main(int argc, char *argv[]) { int server_sockfd, client_sockfd; int server_len, client_len; struct sockaddr_un server_address; struct sockaddr_un client_address; int i, bytes; char ch_send, ch_recv; pthread_t send_id, recv_id; unlink(SERVER_SOCK_PATH); server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (-1 == server_sockfd) { perror("socket"); exit(-1); } server_address.sun_family = AF_UNIX; strcpy(server_address.sun_path, SERVER_SOCK_PATH); server_len = sizeof(server_address); bind(server_sockfd, (struct sockaddr *)&server_address, server_len); listen(server_sockfd, 5); client_len = sizeof(client_address); client_sockfd = accept(server_sockfd, (struct sockaddr *)&server_address, (socklen_t *)&client_len); if (client_sockfd == -1) { perror("accept"); close (server_sockfd); exit(-1); } pthread_create(&send_id, NULL, send_data, &client_sockfd); pthread_create(&recv_id, NULL, recv_data, &client_sockfd); pthread_join(send_id,NULL); pthread_join(recv_id,NULL); close(client_sockfd); return 0; } void *send_data(void *param) { int sock = 0; int ret = 0; int send_len = 0; fd_set sendfd; struct timeval timeout={1,0}; char string_send[128] = {0}; sock = *(int *)param; while(1) { printf("Please enter string to send:\r\n"); memset(string_send, 0, sizeof(string_send)); scanf("%s", string_send); FD_ZERO(&sendfd); FD_SET(sock, &sendfd); ret = select(sock + 1, NULL, &sendfd, NULL, &timeout); if (ret <= 0) { continue; } if (FD_ISSET(sock, &sendfd)) { send_len = send(sock, string_send, strlen(string_send), 0); if (strlen(string_send) != send_len) { printf("send string fail!\r\n"); continue; } } } return; } void *recv_data(void *param) { int sock = 0; int ret = 0; int recv_len = 0; fd_set recvfd; struct timeval timeout={1,0}; char string_recv[128] = {0}; sock = *(int *)param; while(1) { FD_ZERO(&recvfd); FD_SET(sock, &recvfd); ret = select(sock + 1, &recvfd, NULL, NULL, &timeout); if (ret <= 0) { continue; } if (FD_ISSET(sock, &recvfd)) { recv_len = recv(sock, string_recv, sizeof(string_recv), 0); if (recv_len <= 0) { printf("recv string fail!\r\n"); continue; } printf("recv string:%s\r\n", string_recv); } } return; }
4、测试结果。
略(功能可以保证已经实现,公司网络不能上传图片,&…#*%&*…(@¥…&)。
相关文章推荐
- java-模拟tomcat服务器
- Linux socket 初步
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断