一、域套接字相关概念
1>	只能在同一主机之间完成多个进程间的通信方式,是最原始的套接字通信模型
2>	由于不需要借助网络,所以在通信时,无需使用ip地址和端口号
3>	会在内核空间使用 套接字文件 进行通信
4>	bcd-lsp 中的s,说的就是套接字文件类型
5>	socket函数的说明
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 |        #include <sys/types.h>          #include <sys/socket.h>
 
 int socket(int domain, int type, int protocol);
 功能:创建一个用于通信的端点,并返回该通信对应的文件描述符,描述符使用最小未分配原则
 参数1:通信域对应的协议族
 AF_UNIX, AF_LOCAL   Local communication(本地通信)              unix(7) man 7 unix可以查看相信信息
 AF_INET             IPv4 Internet protocols(IPv4通信)          ip(7)   man 7 ip可以查看相信信息
 AF_INET6            IPv6 Internet protocols(IPv6通信)          ipv6(7) man 7 ipv6可以查看相信信息
 参数2:指定通信语义,理解成传输方式
 SOCK_STREAM     提供支持TCP通信
 
 SOCK_DGRAM      提供支持UDP通信
 SOCK_RAW        通过原始的套接字通信
 参数3:通信协议,如果参数2指定了确定的通信方式,该参数填0即可
 如果不确定通信方式,可用的参数有:
 TCP:IPPROTO_TCP
 UDP:IPPROTO_UDP
 返回值:成功返回套接字文件描述符,失败返回-1并置位错误码
 
 
 | 
二、流式域套接字
1>	基于TCP通信原理,面向连接的通信方式
2>	bind函数,只能绑定一个不存在的套接字文件,如果绑定的套接字文件存在,则bind函数报错:Address already in use
3>	对于客户端而言,如果不绑定一个套接字文件,系统不会给客户端绑定套接字文件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 
 |        #include <sys/types.h>          #include <sys/socket.h>
 
 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 功能:给指定的套接字文件描述符绑定IP地址和端口号
 参数1:要绑定的套接字文件描述符
 参数2:地址信息结构体,包含了通信域、IP地址、端口号
 struct sockaddr {
 sa_family_t sa_family;
 char        sa_data[14];
 }
 以上结构体是通用地址信息结构体,无论TCP还是UDP都可以使用,主要用于形参的强制类型转换,避免出现编译报错,但是具体的通信族有不同的地址信息结构体
 对于IPv4通信,需要man 7 ip进行查看
 struct sockaddr_in {
 sa_family_t    sin_family;       通信域
 in_port_t      sin_port;      端口号,网络字节序
 struct in_addr sin_addr;                网络地址,是一个结构体
 };
 struct in_addr {
 uint32_t       s_addr;        IP地址,网络字节序
 };
 
 对于本地的通信,需要man 7 unix查看
 struct sockaddr_un {
 sa_family_t sun_family;                      标识域套接字
 char        sun_path[108];                  套接字文件的名字
 };
 参数3:参数2的大小
 返回值:   成功返回0,失败返回-1并置位错误码
 
 
 
 
 | 
3>	判断文件是否存在函数:access
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 |        #include <unistd.h>
 int access(const char *pathname, int mode);
 功能:判断给定的文件是否具有给定的权限
 参数1:要检测的文件,是一个文件路径
 参数2:要检测的权限
 R_OK:判断是否具有读权限
 W_OK:判断是否具有写权限
 X_OK:判断是否具有可执行权限
 F_OK:判断是否存在
 返回值:如果检查的权限存在,则返回0,否则返回-1并置位错误码
 
 | 
4>	删除文件系统中某个文件的函数:unlink
| 12
 3
 4
 5
 6
 
 |        #include <unistd.h>
 int unlink(const char *path);
 功能:删除指定的文件
 参数:要删除的文件文件路径
 返回值:成功返回0,失败返回-1并置位错误码
 
 | 
2.1	流式域套接字服务器端实现
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 
 | #include<myhead.h>
 int main(int argc, const char *argv[])
 {
 
 int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
 
 if(sfd == -1)
 {
 perror("socket error");
 return -1;
 }
 
 
 
 
 if(access("./unix", F_OK) == 0)
 {
 
 if(unlink("./unix")==-1)
 {
 perror("unlink error");
 return -1;
 }
 }
 
 
 struct sockaddr_un sun;
 sun.sun_family = AF_UNIX;
 
 strcpy(sun.sun_path, "./unix");
 
 
 if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) == -1)
 {
 perror("bind error");
 return -1;
 }
 printf("bind success\n");
 
 
 if(listen(sfd, 128) ==-1)
 {
 perror("listen error");
 return -1;
 }
 
 
 
 struct sockaddr_un cun;
 socklen_t socklen = sizeof(cun);
 
 int newfd = accept(sfd, (struct sockaddr*)&cun, &socklen);
 if(newfd == -1)
 {
 perror("accept error");
 return -1;
 }
 
 
 char buf[128] = "";
 while(1)
 {
 
 bzero(buf, sizeof(buf));
 
 int res = recv(newfd, buf, sizeof(buf), 0);
 if(res == 0)
 {
 printf("客户端已经下线\n");
 break;
 }
 printf("[%s]: %s\n", cun.sun_path ,buf);
 
 }
 
 
 close(newfd);
 close(sfd);
 
 
 return 0;
 }
 
 
 | 
2.2	流式域套接字客户端实现
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 
 | #include<myhead.h>
 int main(int argc, const char *argv[])
 {
 
 int cfd = -1;
 cfd = socket(AF_UNIX, SOCK_STREAM, 0);
 if(cfd == -1)
 {
 perror("socket error");
 return -1;
 }
 printf("cfd = %d\n", cfd);
 
 
 
 if(access("./linux", F_OK) == 0)
 {
 
 if(unlink("./linux")==-1)
 {
 perror("unlink error");
 return -1;
 }
 }
 
 
 
 
 
 
 struct sockaddr_un cun;
 cun.sun_family = AF_UNIX;
 strcpy(cun.sun_path,"./linux");
 
 
 if(bind(cfd, (struct sockaddr*)&cun, sizeof(cun)) == -1)
 {
 perror("bind error");
 return  -1;
 }
 printf("bind  success\n");
 
 
 
 
 struct sockaddr_un sun;
 sun.sun_family = 	AF_UNIX;
 strcpy(sun.sun_path, "./unix");
 
 
 if(connect(cfd, (struct sockaddr*)&sun, sizeof(sun)) == -1)
 {
 perror("connect error");
 return -1;
 }
 printf("connect success\n");
 
 
 
 char buf[128] = "";
 while(1)
 {
 
 bzero(buf, sizeof(buf));
 
 printf("请输入>>>");
 fgets(buf, sizeof(buf), stdin);
 buf[strlen(buf)-1] = 0;
 
 
 send(cfd, buf, sizeof(buf), 0);
 printf("发送成功\n");
 if(strcmp(buf, "quit") == 0)
 {
 break;
 }
 
 
 }
 
 
 close(cfd);
 
 return 0;
 }
 
 
 | 
三、报式域套接字
1>	基于UDP面向无连接的通信方式
2>	如果客户端没有绑定套接字,系统不会为其绑定套接字文件,当服务器想要给客户端发消息时:怎么办?
3.1	报式域套接字服务器端
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 
 | #include<myhead.h>
 
 int main(int argc, const char *argv[])
 {
 
 int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
 
 if(sfd == -1)
 {
 perror("socket error");
 return -1;
 }
 printf("sfd = %d\n", sfd);
 
 
 
 if(access("./linux", F_OK) == 0)
 {
 
 if(unlink("./linux")==-1)
 {
 perror("unlink error");
 return -1;
 }
 }
 
 
 
 
 struct sockaddr_un sun;
 sun.sun_family = AF_UNIX;
 strcpy(sun.sun_path, "./linux");
 
 
 if(bind(sfd, (struct sockaddr*)&sun, sizeof(sun)) == -1)
 {
 perror("bind error");
 return -1;
 }
 
 
 char buf[128] = "";
 
 struct sockaddr_un cun;
 socklen_t socklen = sizeof(cun);
 
 
 while(1)
 {
 
 bzero(buf, sizeof(buf));
 
 
 recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cun, &socklen);
 
 
 printf("[%s]:%s\n", cun.sun_path, buf);
 
 
 strcat(buf, "*_*");
 
 if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cun, sizeof(cun)) == -1)
 {
 perror("write error");
 return -1;
 }
 printf("发送成功\n");
 }
 
 
 close(sfd);
 
 return 0;
 }
 
 
 | 
3.2	报式域套接字客户端
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 
 | #include<myhead.h>
 
 int main(int argc, const char *argv[])
 {
 
 int cfd = socket(AF_UNIX, SOCK_DGRAM, 0);
 if(cfd == -1)
 {
 perror("socket error");
 return -1;
 }
 
 
 
 if(access("./unix", F_OK) == 0)
 {
 
 if(unlink("./unix")==-1)
 {
 perror("unlink error");
 return -1;
 }
 }
 
 
 
 
 struct sockaddr_un cun;
 cun.sun_family = AF_UNIX;
 strcpy(cun.sun_path, "./unix");
 
 
 if(bind(cfd, (struct sockaddr*)&cun, sizeof(cun)) == -1)
 {
 perror("bind error");
 return -1;
 }
 
 
 
 
 
 struct sockaddr_un sun;
 sun.sun_family = AF_UNIX;
 strcpy(sun.sun_path, "./linux");
 
 
 
 char buf[128] = "";
 while(1)
 {
 printf("请输入>>>");
 fgets(buf, sizeof(buf), stdin);
 buf[strlen(buf)-1] = '\0';
 
 
 sendto(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sun, sizeof(sun));
 
 if(strcmp(buf, "quit") == 0)
 {
 break;
 }
 
 
 recvfrom(cfd, buf, sizeof(buf), 0, NULL, NULL);
 printf("收到消息:%s\n", buf);
 
 
 }
 
 
 close(cfd);
 
 
 return 0;
 }
 
 
 | 
本章完