socket介绍,使用socket在同一计算机中的进程间通信

文件目录 

一、socket介绍

一、定义与功能

二、工作原理

三、类型

四、socket在本地进程间通讯应用

二、socket本地进程间通讯实现 

1.服务端

 2.客户端


一、socket介绍

Socket(套接字)是计算机网络中的一个重要概念,它指的是一种用于网络通信的编程接口。以下是关于Socket的详细解释:

一、定义与功能

  • 定义:Socket是应用层与传输层之间的接口,它提供了一种标准的通信方式,使得不同的程序能够在网络上进行数据交换。Socket可以被视为网络通信的端点,它在网络上标识了一个通信链路的两端,并提供了通信双方所需的接口和功能。
  • 功能:Socket允许应用程序通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。它允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。

二、工作原理

Socket的工作原理可以简单概括为以下几个步骤:

  1. 创建Socket:应用程序通过调用socket()函数创建一个Socket对象,并指定Socket的类型(如TCP或UDP)。
  2. 绑定地址和端口(仅服务器端):服务器端通过调用bind()函数将Socket对象与一个特定的IP地址和端口号绑定,这个端口就是服务器的标识,用于在网络上与其他主机建立连接。
  3. 监听连接(仅服务器端):服务器端通过调用listen()函数开始监听来自客户端的连接请求。
  4. 连接请求(客户端):客户端通过调用connect()函数向服务器发送连接请求,指定服务器的IP地址和端口号。
  5. 接受连接(服务器端):当服务器端监听到来自客户端的连接请求后,通过调用accept()函数接受连接请求,并返回一个新的Socket对象,用于与客户端进行通信。
  6. 数据传输:一旦建立连接,服务器和客户端就可以通过各自的Socket对象进行数据传输。它们通过读取和写入Socket对象上的数据流来发送和接收数据。
  7. 关闭连接:当通信完成或者出现错误时,可以通过关闭Socket对象来结束连接,释放资源。

三、类型

Socket主要分为两种类型:

  • TCP Socket:基于TCP协议,提供面向连接的、可靠的、字节流的服务。在TCP协议中,建立连接通常需要进行三次握手,以保证数据的可靠传输。
  • UDP Socket:基于UDP协议,提供无连接的、不可靠的、数据报的服务。UDP协议不保证数据的可靠性,但传输速度较快,适用于实时性要求较高的场景。

四、socket在本地进程间通讯应用

Socket(套接字)虽然主要用于不同主机之间的网络通信,但在同一主机上,进程间通信(IPC)也可以使用Socket,尤其是当需要模拟网络环境下的通信行为时。不过,在同一主机上进行进程间通信时,更常用的方式可能包括管道、消息队列、共享内存等。

二、socket本地进程间通讯实现 

1.服务端

代码如下(示例):

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

int sockfd = 0;
int fd = 0;

void hander(int sig)
{		
	puts("关闭socket");
	if(sockfd)
		close(sockfd);
	if(fd)
		close(fd); 
		
	puts("删除socket");
	const char *socket_path = "/tmp/my_socket.sock"; // 假设这是你的socket文件路径  
  
    // 删除socket文件  
    if (unlink(socket_path) == -1) {  
        perror("unlink");  
    } else {  
        printf("Socket file %s deleted.\n", socket_path);  
    }  
  
    exit(0);  
}
  
int main(int argc , const char* argv[])  
{  
	// 注册信号处理函数
	if(signal(SIGINT, hander) == SIG_ERR)
	{
		perror("signal");
		return EXIT_FAILURE; 
	}
	
    // 创建socket  
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0); // AF_LOCAL 通常是 AF_UNIX 的别名  
    if (sockfd < 0)  
    {  
        perror("socket");  
        return EXIT_FAILURE;  
    }  
  
    // 准备通信地址(本地socket地址)  
    struct sockaddr_un addr = {};  
    addr.sun_family = AF_UNIX;  
    strcpy(addr.sun_path, "/tmp/my_socket.sock"); // 注意确保路径的唯一性和可访问性   
  
    socklen_t addrlen = sizeof(addr);  
    // 绑定socket和地址  
    if (bind(sockfd, (struct sockaddr *)&addr, addrlen) < 0)  
    {  
        perror("bind");  
        return EXIT_FAILURE;  
    }  
      
    // 开启监听   
    if (listen(sockfd, 5) < 0)   
    {  
        perror("listen");  
        return EXIT_FAILURE;  
    }  
  
    // 等待连接  
    fd = accept(sockfd, (struct sockaddr *)&addr, &addrlen);  
    if (fd < 0)  
    {  
        perror("accept");  
        return EXIT_FAILURE;  
    }  
  
    char buf[4096] = {};  
    size_t buf_size = sizeof(buf) - 1; // 留出空间给终止符  
  
    while (1)  
    {   
        fflush(stdout); // 刷新输出缓冲区  
  
        ssize_t ret_size = read(fd, buf, buf_size);  
        if (ret_size > 0)  
        {  
            buf[ret_size] = '\0'; // 加上终止符  
            if (strncmp(buf, "quit", 4) == 0) // 使用 strncmp 来比较前 4 个字符  
            {  
                printf("通讯结束\n");  
                break;  
            }  
  
            printf("\nrecv:%s\n>>>>", buf);  
    
            if (fgets(buf, buf_size, stdin) != NULL)  
            {  
                // 去掉可能的换行符  
                buf[strcspn(buf, "\n")] = 0;  
                write(fd, buf, strlen(buf)); // 不需要发送终止符  
  
                if (strncmp(buf, "quit", 4) == 0)  
                {  
                    printf("通讯结束\n");  
                    break;  
                }  
            }  
        }  
        else if (ret_size == 0)  
        {  
            // 对端关闭连接  
            printf("对端关闭连接\n"); 
            break;  
        }  
        else  
        {  
            // 错误处理  
            perror("read");  
            break;  
        }  
    }  
      
    // 关闭socket  
    close(fd);  
    close(sockfd);  
      
    // 删除socket文件  
    unlink(addr.sun_path);  
    return 0;   
}

 2.客户端

代码如下(示例):

#include <stdio.h>  
#include <sys/types.h>           
#include <sys/socket.h>  
#include <string.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <sys/un.h> 
 
int main(int argc , const char* argv[])  
{  
    // 创建socket  
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);  
    if (sockfd < 0)  
    {  
        perror("socket");  
        return EXIT_FAILURE;  
    }  
      
    // 准备通信地址(本地socket地址)  
    struct sockaddr_un addr = {};  
    addr.sun_family = AF_UNIX;  
    strcpy(addr.sun_path, "/tmp/my_socket.sock");  
      
    // 连接  
    if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)  
    {  
        perror("connect");  
        return EXIT_FAILURE;  
    }  
      
    char buf[4096] = {};  
    size_t buf_size = sizeof(buf) - 1; // 留出空间给终止符  
  
    while(1)  
    {  
    	fflush(stdout); // 刷新输出缓冲区
    	printf(">>>");
    	if(fgets(buf, buf_size, stdin) != NULL)  
        {  
            // 去掉可能的换行符  
            buf[strcspn(buf, "\n")] = 0;  
            write(sockfd, buf, strlen(buf)); // 不需要发送终止符    
        } 
        
        ssize_t ret_size = read(sockfd, buf, buf_size); 
        if(ret_size > 0)  
        {  
            buf[ret_size] = '\0'; // 添加终止符  
  
            // 检查是否收到 "quit"  
            if (strstr(buf, "quit") != NULL)  
            {  
                printf("通讯结束\n");  
                break;  
            }  
  
            printf("\nrecv:%s\n", buf);   
        }  
        else if (ret_size == 0)  
        {  
            // 对端关闭连接  
            printf("对端关闭连接\n");  
            break;  
        }  
        else  
        {  
            // 错误处理  
            perror("read");  
            break;  
        }  
    }  
      
    // 关闭socket  
    close(sockfd);  
    return 0;  
}

三、本内容的其他博客链接 

https://blog.csdn.net/qq_43290168/article/details/119078595

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值