简述:
本地套接字的使用与网络套接字的使用大体上是类似的,但是也存在一些区别,主要有(1)和套接字绑定的地址结构体不同,本地套接字使用的结构体是 struct sockaddr_un ,而网络套接字使用的是 struct sockaddr_in;(2)协议族不同,本地套接字使用的是AF_UNIX 或AF_LOCAL, 网络套接字常用的是AF_INET;(3)对于使用本地套接字的C/S模型,服务器和客户端都需要显式绑定套接字描述符和地址信息,即(1)中提到的存放地址信息的结构体;(4)用本地套接字的C/S模型中,服务器和客户端都是通过 bind 函数创建本地套接字伪文件,服务器和客户端之间即是通过各自的套接字伪文件来产生连接然后进行数据通信。其余不同具体见代码。
1、服务器端代码
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cctype>
#include <sys/un.h>
#include <stddef.h>
#include "wrap.h"
#define SERV_ADDR "serv.socket"
int main()
{
int lfd, cfd, len, size, i;
struct sockaddr_un servaddr, clieaddr;
char buf[4096];
lfd = Socket(AF_UNIX, SOCK_STREAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, SERV_ADDR);
len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);
unlink(SERV_ADDR); // Make sure that the file("serv.socket") does not exist before bind,bacause
// bind will create it.
Bind(lfd, (struct sockaddr *)&servaddr, len); // Note that the third parameter passed in is "len".
Listen(lfd, 20);
printf("Accept...\n");
while(1) {
len = sizeof(clieaddr);
cfd = Accept(lfd, (struct sockaddr *)&clieaddr, (socklen_t *)&len);
len -= offsetof(struct sockaddr_un, sun_path); // Get the length of the file name of the client's local socket
clieaddr.sun_path[len] = '\0';
printf("client bind filename %s\n", clieaddr.sun_path);
while((size = Read(cfd, buf, sizeof(buf))) > 0) {
for(i = 0; i < size; i++)
buf[i] = toupper(buf[i]);
Write(cfd, buf, size);
}
close(cfd);
}
close(lfd);
return 0;
}
2、客户端代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <cctype>
#include <cstddef>
#include "wrap.h"
#define SERV_ADDR "serv.socket"
#define CLIE_ADDR "clie.socket"
int main()
{
int cfd, len;
struct sockaddr_un servaddr, clieaddr;
char buf[4096];
cfd = Socket(AF_UNIX, SOCK_STREAM, 0);
memset(&clieaddr, 0, sizeof(clieaddr));
clieaddr.sun_family = AF_UNIX;
strcpy(clieaddr.sun_path, CLIE_ADDR);
len = offsetof(struct sockaddr_un, sun_path) + strlen(clieaddr.sun_path);
unlink(CLIE_ADDR);
Bind(cfd, (struct sockaddr *)&clieaddr, len);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, SERV_ADDR);
len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);
Connect(cfd, (struct sockaddr *)&servaddr, len);
while(fgets(buf, sizeof(buf), stdin) != NULL) {
Write(cfd, buf, strlen(buf));
len = Read(cfd, buf, sizeof(buf));
Write(STDOUT_FILENO, buf, len);
}
close(cfd);
return 0;
}