UNIX域套接字

一、UNIX域流式套接字

1.本地地址

struct sockaddr_un {

        unsigned short sun_family;    /* 协议类型 */

        char sun_path[108];        /* 套接字文件路径 */

};

2.UNIX域流式套接字

UNIX 域流式套接字的用法和TCP套接字基本一致,区别在于使用的协议和地址不同

UNIX 域流式套接字服务器端流程如下:

(1)创建 UNIX 域流式套接字。

(2)绑定本地地址(套接字文件)。

(3)设置监听模式。

(4)接收客户端的连接请求。

(5)发送/接收数据。

UNIX 域流式套接字客户端流程如下。

(1)创建 UNIX 域流式套接字。

(2)指定服务器端地址(套接字文件)。

(3)建立连接。

(4)发送/接收数据。

示例:

server.c

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/my_sock_file"
#define LISTEN_BACKLOG 50

#define handle_error(msg) \
	do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
	int sfd, cfd;
	struct sockaddr_un my_addr, peer_addr;
	socklen_t peer_addr_size;
	char buf[BUFSIZ] = {};

	sfd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sfd == -1)
		handle_error("socket");

	memset(&my_addr, 0, sizeof(struct sockaddr_un));
	my_addr.sun_family = AF_UNIX;
	strncpy(my_addr.sun_path, MY_SOCK_PATH,
			sizeof(my_addr.sun_path) - 1);

	if (bind(sfd, (struct sockaddr *) &my_addr,
				sizeof(struct sockaddr_un)) == -1)
		handle_error("bind");
	if (listen(sfd, LISTEN_BACKLOG) == -1)
		handle_error("listen");

	peer_addr_size = sizeof(struct sockaddr_un);
	cfd = accept(sfd, (struct sockaddr *) &peer_addr,
			&peer_addr_size);
	if (cfd == -1)
		handle_error("accept");
	
	recv(cfd, buf, BUFSIZ, 0);
	printf("%s\n", buf);

	close(cfd);
	close(sfd);
	remove(MY_SOCK_PATH);
	return 0;
}

client.c

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/my_sock_file"

#define handle_error(msg) \
	do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
	int fd;
	struct sockaddr_un peer_addr;
	char buf[BUFSIZ] = {"Hello World!"};

	fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (fd == -1)
		handle_error("socket");

	memset(&peer_addr, 0, sizeof(struct sockaddr_un));
	peer_addr.sun_family = AF_UNIX;
	strncpy(peer_addr.sun_path, MY_SOCK_PATH,
			sizeof(peer_addr.sun_path) - 1);

	if (connect(fd, (struct sockaddr *) &peer_addr,
				sizeof(struct sockaddr_un)) == -1)
		handle_error("connect");

	printf("%s\n",buf);
	send(fd, buf, strlen(buf), 0);

	close(fd);
	return 0;
}

二、UNIX域数据报套接字

UNIX 域用户数据报套接字的流程可参考 UDP 套接字

UNIX 域流式套接字服务器端流程如下:

(1)创建 UNIX 域流式套接字。

(2)绑定本地地址(套接字文件)。

(3)发送/接收数据。

示例:

server.c

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/my_sock_file"
#define handle_error(msg) \
	do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
	int fd;
	struct sockaddr_un my_addr, peer_addr;
	socklen_t peer_addr_size;
	char buf[BUFSIZ] = {};

	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (fd == -1)
		handle_error("socket");

	memset(&my_addr, 0, sizeof(struct sockaddr_un));
	my_addr.sun_family = AF_UNIX;
	strncpy(my_addr.sun_path, MY_SOCK_PATH,
			sizeof(my_addr.sun_path) - 1);

	if (bind(fd, (struct sockaddr *) &my_addr,
				sizeof(struct sockaddr_un)) == -1)
		handle_error("bind");

	peer_addr_size = sizeof(struct sockaddr_un);
	recvfrom(fd, buf, BUFSIZ, 0, (struct sockaddr *) &peer_addr,
			&peer_addr_size);
	printf("%s\n",buf);
	close(fd);
	remove(MY_SOCK_PATH);
	return 0;
}

client.c

#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MY_SOCK_PATH "/tmp/my_sock_file"
#define handle_error(msg) \
	do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
	int fd;
	struct sockaddr_un peer_addr;
	socklen_t peer_addr_size;
	char buf[BUFSIZ] = {"Hello World!"};

	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (fd == -1)
		handle_error("socket");

	memset(&peer_addr, 0, sizeof(struct sockaddr_un));
	peer_addr.sun_family = AF_UNIX;
	strncpy(peer_addr.sun_path, MY_SOCK_PATH,
			sizeof(peer_addr.sun_path) - 1);

	peer_addr_size = sizeof(struct sockaddr_un);
	printf("%s\n", buf);
	sendto(fd, buf, strlen(buf), 0, (struct sockaddr *) &peer_addr,
			peer_addr_size);
	close(fd);
	remove(MY_SOCK_PATH);
	return 0;
}

Makefile

CC=gcc
CFLAGS=-Wall
all:server client

clean:
		rm server client

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 C++ 程序,用于在 UNIX 上进行套接字通信: ```cpp #include <iostream> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <cstring> const char* SOCKET_PATH = "/tmp/mysocket"; int main() { // 创建套接字 int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd == -1) { std::cerr << "Failed to create socket" << std::endl; return 1; } // 绑定到 socket 地址 struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1); if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { std::cerr << "Failed to bind socket" << std::endl; close(sockfd); return 1; } // 监听连接请求 if (listen(sockfd, 5) == -1) { std::cerr << "Failed to listen on socket" << std::endl; close(sockfd); return 1; } // 等待客户端连接 int clientfd = accept(sockfd, nullptr, nullptr); if (clientfd == -1) { std::cerr << "Failed to accept client" << std::endl; close(sockfd); return 1; } // 读取客户端发送的数据 char buf[256]; int numBytes = read(clientfd, buf, sizeof(buf)); if (numBytes == -1) { std::cerr << "Failed to read from client" << std::endl; close(clientfd); close(sockfd); return 1; } // 打印接收到的数据 std::cout << "Received " << numBytes << " bytes: " << buf << std::endl; // 关闭套接字 close(clientfd); close(sockfd); return 0; } ``` 在这个程序中,我们首先使用 `socket` 函数创建了一个 UNIX 套接字。然后,我们使用 `bind` 函数将套接字绑定到一个本地地址上,这里我们使用了 `/tmp/mysocket` 作为地址。接下来,我们使用 `listen` 函数开始监听连接请求。当有客户端连接时,使用 `accept` 函数接受连接请求,并返回一个新的套接字,可以使用这个套接字与客户端进行通信。在这个程序中,我们只是简单地从客户端读取数据,并将其打印到标准输出流中。最后,我们关闭套接字并退出程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值