08 Linux进程间通信网络套接字socket Demo

08 Linux进程间通信网络套接字socket Demo

作者 将狼才鲸
创建日期 2023-03-05

  • 运行效果:
jim@ubuntu:/mnt/hgfs/git_win10/many-repositories/24_Linux套接字SocketDemo$ make
gcc -o server server.c
gcc -o client client.c
jim@ubuntu:/mnt/hgfs/git_win10/many-repositories/24_Linux套接字SocketDemo$ make run
./server &
sleep 1
waitting for client connect...
./client
waitting for client send data...
client-->server[24]: Client say hello world!
client<==server[16]: server received
client-->server[18]: My name is client
client<==server[16]: server received
client-->server[29]: e(exit). I will close server
jim@ubuntu:/mnt/hgfs/git_win10/many-repositories/24_Linux套接字SocketDemo$ 

  • 源码:
  1. Makefile:
default:
	gcc -o server server.c
	gcc -o client client.c
run:
	./server &
	sleep 1
	./client
clean:
	rm server client

  1. comm.h:
/******************************************************************************
 * \brief	Linux进程间通信网络套接字socket Demo
 * \note	File format: UTF-8,中文编码:UTF-8
 * \remarks	[Linux之本地进程间Socket通信](https://blog.csdn.net/landishu/article/details/118182019)
 * \author	将狼才鲸
 * \date	2023-03-05
 ******************************************************************************/

#ifndef _COMM_H_
#define _COMM_H_

#define SOCKET_FILE "/tmp/linux.socket"	/* 本机通信使用的虚拟内存文件 */
#define RECV_BUF_SIZE 1024

#endif /* _COMM_H_ */

  1. server.c:

#include <sys/socket.h>	/* socket AF_UNIX SOCK_STREAM sockaddr bind accept */
#include <sys/un.h>		/* sockaddr_un */
#include <stdio.h>		/* perror printf */
#include <string.h>		/* strcpy */
#include <unistd.h>		/* unlink read write close */
#include "comm.h"

#define SERVER_STRING "server received"

static char recv_buf[RECV_BUF_SIZE];

int main()
{
    
    
	struct sockaddr_un srv_addr;	/* 服务器域套接字地址 */
	struct sockaddr_un clt_addr; 
	int listen_fd, connect_fd;
	int ret;
	
	/* 打开一个套接字,地址族协议:本地IPC通信(非ipv4或ipv4),
	   套接字类型:流,使用的协议:无(非TCP或UDP) */
	listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (listen_fd < 0) {
    
    
		perror("socket");
		return -1;
	}
	
	srv_addr.sun_family = AF_UNIX;	/* 本机IPC通信 */
	strcpy(srv_addr.sun_path, SOCKET_FILE);	/* 使用虚拟内存文件 */
	
	unlink(SOCKET_FILE);	/* 绑定前先取消本地内存文件链接,防止绑定报错 */
	/* 绑定套接字和协议,使用本地内存文件 */
	ret = bind(listen_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
	if (ret < 0) {
    
    
		perror("bind");
		goto exit1;
	}

	printf("waitting for client connect...\n");

#define LISTEN_MAX_NUM 8	/* 允许监听但还未链接的链路总数 */
	/* 监听链路 */
	ret = listen(listen_fd, LISTEN_MAX_NUM);
	if (ret < 0) {
    
    
		perror("listen");
		goto exit1;
	}

	int clt_addr_len = sizeof(clt_addr); 
	/* 等待客户端握手连接 */
	connect_fd = accept(listen_fd, (struct sockaddr *)&clt_addr, &clt_addr_len);
	if (ret < 0) {
    
    
		perror("accept");
		goto exit1;
	}

	printf("waitting for client send data...\n");

	/* 收发收据 */
	int len;
	while (1) {
    
    
		/* 按期望的最大长度进行读取,返回实际读到的长度,
		   没读到数据会一直阻塞住,想要不阻塞需要额外添加pselect函数 */
		len = read(connect_fd, recv_buf, sizeof(recv_buf));
		if (len > 0) {
    
    
			recv_buf[len] = '\0';
			printf("client-->server[%d]: %s\n", len, recv_buf);
			write(connect_fd, SERVER_STRING, sizeof(SERVER_STRING));
			if (recv_buf[0] == 'e')	/* 自定义一个退出消息 */
				goto exit2;
		}
	}

exit2:
	/* 关闭连接 */
	close(connect_fd);

exit1:
	unlink(SOCKET_FILE);
	/* 关闭套接字 */
	close(listen_fd);
	
	return 0;
}

  1. client.c:
#include <sys/socket.h>	/* socket AF_UNIX SOCK_STREAM sockaddr connect */
#include <sys/un.h>		/* sockaddr_un */
#include <stdio.h>		/* perror printf */
#include <string.h>		/* strcpy */
#include <unistd.h>		/* unlink read write close */
#include "comm.h"

#define CLIENT_STRING1 "Client say hello world!"
#define CLIENT_STRING2 "My name is client"
#define CLIENT_STRING3 "e(exit). I will close server"

static char recv_buf[RECV_BUF_SIZE];

int main(void)
{
    
    
	struct sockaddr_un srv_addr;	/* 服务器域套接字地址 */
	struct sockaddr_un clt_addr; 
	int connect_fd;
	int ret, len;

	/* 打开一个套接字,地址族协议:本地IPC通信(非ipv4或ipv4),
	   套接字类型:流,使用的协议:无(非TCP或UDP) */
	connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (connect_fd < 0) {
    
    
		perror("socket");
		return -1;
	}

	srv_addr.sun_family = AF_UNIX;	/* 本机IPC通信 */
	strcpy(srv_addr.sun_path, SOCKET_FILE);	/* 使用虚拟内存文件 */
	
	/* 握手和连接服务器端 */
	ret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
	if (ret < 0) {
    
    
		perror("bind");
		goto exit;
	}

	/* 收发数据 */
	write(connect_fd, CLIENT_STRING1, sizeof(CLIENT_STRING1));
	len = read(connect_fd, recv_buf, sizeof(recv_buf));
	if (len > 0) {
    
    
		recv_buf[len] = '\0';
		printf("client<==server[%d]: %s\n", len, recv_buf);
	}

	write(connect_fd, CLIENT_STRING2, sizeof(CLIENT_STRING2));
	len = read(connect_fd, recv_buf, sizeof(recv_buf));
	if (len > 0) {
    
    
		recv_buf[len] = '\0';
		printf("client<==server[%d]: %s\n", len, recv_buf);
	}

	write(connect_fd, CLIENT_STRING3, sizeof(CLIENT_STRING3));

exit:
	/* 关闭套接字 */
	close(connect_fd);

	return 0;
}


猜你喜欢

转载自blog.csdn.net/qq582880551/article/details/129349670