Home  >  Article  >  System Tutorial  >  Linux IPC udp/ip socket programming: an efficient way to achieve network communication

Linux IPC udp/ip socket programming: an efficient way to achieve network communication

王林
王林forward
2024-02-11 10:51:29403browse

Linux system is an operating system that supports concurrent execution of multi-tasks. It can run multiple processes at the same time, thereby improving system utilization and efficiency. However, if data exchange and collaboration are required between these processes, some inter-process communication (IPC) methods need to be used, such as signals, message queues, shared memory, semaphores, etc. Among them, udp/ip socket is a relatively efficient and flexible IPC method. It allows two or more processes to transmit data through the network without caring about the specific details and protocols of the network.

Linux IPC udp/ip socket 编程:一种实现网络通信的高效方式
#include 
#include 
#include 
#include 
#include 
//服务器:    

socket()              //创建socket            
struct sockaddr_in    //准备通信地址
bind()                //绑定socket和addr 
sendto()/recvfrom     //进行通信
close()               //关闭socket

//客户端:

socket()              //创建socket:
//准备通信地址:服务器的地址
sendto()/recv()       //进行通信:
close()               //关闭socket:

socket()

//创建网络端点,返回socket文件描述符,失败返回-1设errno

int socket(int domain, int type, int protocol);

domain: Protocol family (network communication (IP) or local communication (xxx.socket))

  • AF_INET Used to implement the network protocol given to the ipv4 network protocol
    type: Protocol (TCP or UDP)
  • SOCK_DGRAM //Datagram socket, implementation includes but not limited to UDP protocol, which is unreliable, connectionless datagram communication party
    protocol: Special protocol, general Give 0

Prepare correspondence address:

struct sockaddr{    //主要用于函数的形参类型, 很少定义结构体变量使用, 叫做通用的通信地址类型//$man bind
    sa_family_t     sa_family;
    char            sa_data[14];
}
struct sockaddr_in{ //准备网络通信的通信地址   //$man in.h
    sa_family_t sin_family;     //协议族, 就是socket()的domain的AF_INET
    in_port_t       sin_port;   //端口号
    struct in_addr  sin_addr;   //IP地址,
                    //当前网段的最大ip地址是广播地址,即,xxx.xxx.xxx.255。
                    //255.255.255.255在所有网段都是广播地址
}
struct in_addr{ 
    in_addr_t   s_addr;     //整数类型的IP地址
}

bind()

//把通信地址和socket文件描述符绑定,用在服务器端,成功返回0,失败返回-1设errno

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockfd: The fd of the socket file (returned by socket())
addr: Needs to be cast to socketaddr_un or soketaddr_in, see above
addrlen: The size of the communication address, use sizeof();

sendto()

//向指定的socket和相应的地址发送消息,成功返回实际发送数据的大小,失败返回-1设errno
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct 
sockaddr *dest_addr, socklen_t addrlen);

dest_addr: Destination address (recipient information)
addrlen: The size of the destination address

ANote

  • send(sockfd, buf, len, flags); equivalent to sendto(sockfd, buf, len, flags, NULL, 0);
  • recv()/send() means sending and receiving data through sockfd. Because under tcp, sockfd is already connected to the corresponding address before sending and receiving, so there is no need to specify who to send and receive/to whom, but udp needs to specify because there is no connection during sending and receiving.

recvfrom()

//从指定的socket和相应的地址接受消息,并提供来电显示的功能,成功返回实际接收的数据大小,
失败返回-1设errno
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr 
*src_addr, socklen_t *addrlen);

src_addr: Structure pointer, used to save the communication address of the data sender
addrlen: Pointer type, used to save the sender's address size

Note:

  • recv(sockfd, buf, len, flags); 等价于 recvfrom(sockfd, buf, len, flags, NULL, 0);
  • accept() and recvfrom() 后面的参数是用来提供来电显示的
  • 一个server对应多个client
  • server可以不知道client的地址, 但是client得知道server的地址
  • send data 一定要知道对方地址
  • receive data不需要知道对方地址
  • TCP/IP的socket都是SOCK_STREAM的,全程连接,通过socket就能找到对方地址, send data的话,直接丢给socket就行
  • UDP/IP的socket是SOCK_DGRAM的,不全程连接,不能通过socket找到对方,send data的话,server中需要使用recvfrom()来知道client的地址, 所以肯定要sendto();client本来就知道server的地址, 直接sendto()
  • recvfrom()的唯一意义就是在udp-server中配合sendto()使用
  • 因为不能通过socket找到对方, 只要是udp发消息, 就得通过sendto()
server client
TCP/IP send();recv() send();recv()
UDP/IP recvfrom();sendto() recv();sendto()

例子-一对一的upd/ip协议的服务器模型

//udp/ip server 五步走
#include
#include
#include
#include
#include
#include
#include
int main(){
    //1. 创建socket
    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(-1==sockfd)
        perror("socket"),exit(-1);
    
    //2. 准备通信地址
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(8888);
    addr.sin_addr.s_addr=inet_addr("176.43.11.211");

    //3. 绑定socket和通信地址
    int res=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    if(-1==res)
        perror("bind"),exit(-1);
    printf("bind success\n");

    //4. 进行通信
    char buf[100]={0};
    struct sockaddr_in recv_addr;       //为使用recvfrom得到client地址做准备, 
最终为sendto()做准备
    socklen_t len=sizeof(recv_addr);
    res=recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&recv_addr,&len);
    if(-1==res)
        perror("recvfrom"),exit(-1);

    char* ip=inet_ntoa(recv_addr.sin_addr);             
//将recvfrom获得client地址转换成点分十进制字符串
    printf("data received from client :%s is:%d\n",ip,res); 

    res=sendto(sockfd,"I received",sizeof("I received"),0,(struct sockaddr*)&recv_addr,len)
;//使用recvfrom获得的client地址
    if(-1==res)
        perror("sendto"),exit(-1);

    //5. 关闭socket
    res=close(sockfd);
    if(-1==res)
        perror("close"),exit(-1);
    printf("close success\n");
        
    return 0;
}
//udp/ip client
#include
#include
#include  //close()
#include
#include
#include
#include
int main(){
    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(-1==sockfd)
        perror("socket"),exit(-1);
    printf("create socket succesfully\n");
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(8888);
    addr.sin_addr.s_addr=inet_addr("176.43.11.211");    

//这个是server的地址, 虽然没有

connect, which means 不能通过socket找到这个地址, 但是我们还是知道这个地址的, sendto()是可以直接用的

    int res=sendto(sockfd,"hello",sizeof("hello"),0,(struct sockaddr*)&addr,sizeof(addr));
    if(-1==res)
        perror("sendto"),exit(-1);
    printf("data sent size:%d\n",res);
    char buf[100]={0};
    res=recv(sockfd,buf,sizeof(buf),0);
    if(-1==res)
        perror("recv"),exit(-1);
    printf("data received from server:%s\n",buf);
    res=close(sockfd);
    if(-1==res)
        perror("close"),exit(-1);

    return 0;
}

本文介绍了Linux系统中udp/ip socket编程的方法,包括socket的创建、绑定、发送、接收、关闭和设置等方面。通过了解和掌握这些知识,我们可以更好地使用udp/ip socket来实现进程间通信,提高系统的性能和可靠性。当然,Linux系统中udp/ip socket编程还有很多其他的特性和用法,需要我们不断地学习和探索。

The above is the detailed content of Linux IPC udp/ip socket programming: an efficient way to achieve network communication. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:lxlinux.net. If there is any infringement, please contact admin@php.cn delete