首頁  >  文章  >  系統教程  >  Linux IPC udp/ip socket 程式設計:一種實現網路通訊的高效方式

Linux IPC udp/ip socket 程式設計:一種實現網路通訊的高效方式

王林
王林轉載
2024-02-11 10:51:29336瀏覽

Linux系統是一種支援多任務並發執行的作業系統,它可以同時運行多個進程,從而提高系統的使用率和效率。但是,如果這些進程之間需要進行資料交換和協作,就需要使用一些進程間通訊(IPC)的方式,例如訊號、訊息佇列、共享記憶體、信號量等。其中,udp/ip socket是一種比較高效且靈活的IPC方式,它可以讓兩個或多個進程透過網路來進行資料傳輸,無需關心網路的具體細節和協定。

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)(網路通訊(IP)還是本機通訊(xxx.socket))

  • AF_INET用於實作給予ipv4網路協定的網路協定
    ##type :協定(TCP還是UDP)
  • SOCK_DGRAM //資料報套接字, 實作包含但不限於UDP協定, which is不可靠,無連線的資料報通訊方
    protocol: 特殊協定, 一般給0

#準備通訊位址:
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: socket檔案的fd(returned by socket())
addr: 需要強制型別轉換成socketaddr_un或soketaddr_in, 請參閱上
# addrlen: 通訊位址的大小, 使用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:目標位址(收件者資訊)
addrlen: 目標位址的大小

ANote

    # send(sockfd, buf, len, flags);等價於 sendto(sockfd, buf, len, flags, NULL, 0);
  • # recv()/ send()表示透過sockfd收發資料, 因為tcp下, 收發之前sockfd已經和對應的位址連接了,所以不需要指定收發誰的/給誰, 但是udp因為收發時沒有連線, 所以需要指定

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: 結構體指標, 用於保存資料發送方的通訊位址
addrlen: 指標類型, 用於保存發送方的位址大小

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编程还有很多其他的特性和用法,需要我们不断地学习和探索。

以上是Linux IPC udp/ip socket 程式設計:一種實現網路通訊的高效方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:lxlinux.net。如有侵權,請聯絡admin@php.cn刪除