Linux进程间通信――使用数据报套接字
2016-09
睿丰德信息科技有限公司
- int socket(int domain, int type, int protocol);
- int bind( int socket, const struct sockaddr *address, size_t address_len);
- int sendto(int sockfd, void *buffer, size_t len, int flags, struct sockaddr *to, socklen_t tolen);
- int recvfrom(int sockfd, void *buffer, size_t len,int flags, struct sockaddr *src_from, socklen_t *src_len);
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
- int main()
- {
- int server_sockfd = -1;
- int server_len = 0;
- int client_len = 0;
- char buffer[512];
- int result = 0;
- struct sockaddr_in server_addr;
- struct sockaddr_in client_addr;
- //创建数据报套接字
- server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- //设置监听IP端口
- server_addr.sin_family = AF_INET;
- server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- server_addr.sin_port = htons(9739);
- server_len = sizeof(server_addr);
- //绑定(命名)套接字
- bind(server_sockfd, (struct sockaddr*)&server_addr, server_len);
- //忽略子进程停止或退出信号
- signal(SIGCHLD, SIG_IGN);
- while(1)
- {
- //接收数据,用client_addr来储存数据来源程序的IP端口
- result = recvfrom(server_sockfd, buffer, sizeof(buffer), 0,
- (struct sockaddr*)&client_addr, &client_len);
- if(fork() == 0)
- {
- //利用子进程来处理数据
- buffer[0] += 'a' - 'A';
- sleep(5);
- //发送处理后的数据
- sendto(server_sockfd, buffer, sizeof(buffer),0 ,
- (struct sockaddr*)&client_addr, client_len);
- printf("%c\n", buffer[0]);
- //注意,一定要关闭子进程,否则程序运行会不正常
- exit(0);
- }
- }
- //关闭套接字
- close(server_sockfd);
- }
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <stdlib.h>
- #include <stdio.h>
- int main(int agrc, char *argv[])
- {
- struct sockaddr_in server_addr;
- int server_len = 0;
- int sockfd = -1;
- int result = 0;
- char c = 'A';
- //取第一个参数的第一个字符
- if(agrc > 1)
- c = argv[1][0];
- //创建数据报套接字
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- //设置服务器IP端口
- server_addr.sin_family = AF_INET;
- server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
- server_addr.sin_port = htons(9739);
- server_len = sizeof(server_addr);
- //向服务器发送数据
- sendto(sockfd, &c, sizeof(char), 0,
- (struct sockaddr*)&server_addr, server_len);
- //接收服务器处理后发送过来的数据,由于不关心数据来源,所以把后两个参数设为0
- recvfrom(sockfd, &c, sizeof(char), 0, 0, 0);
- printf("char from server = %c\n", c);
- //关闭套接字
- close(sockfd);
- exit(0);
- }
在本例子中,我们启动了一个服务器程序和三个客户程序,从运行的结果来看,客户端发送给服务器程序的所有请求都得到了处理,即把大写字母变成了小写。recvfrom调用是阻塞的调用,即只有当接收到数据才会返回。
五、数据报套接字与流套接字的比较
1、从使用的便利和效率来讲
我们可以看到使用数据报套接字的确是比使用流套接字简单,而且快速。
因为使用流套接字的程序,客户程序需要调用connect来创建一个到服务器程序的连接,并需要维持这个连接,服务器程序也需要调用listen来创建一个队列来保存未处理的请求,当有数据到达时,服务器也不需要调用accept来接受连接并创建一个新socket描述符来处理请求。
再来看看使用数据报套接字的程序,服务器程序与客户程序所使用的系统调用大致相同,服务器程序只比客户程序多使用了一个bind调用。基于数据报套接字的程序,只需要使用sendto调用来向指定IP端口的程序发送信息,使用recvfrom调用从指向的IP端口接收信息即可。因为它并不需要建立一个连接,接受连接等,所以省去了很多的功夫。
2、从使用场合来讲
我们知道流套接字是基于TCP/IP协议的,它是一种安全的协议,提供的是一个有序、可靠、双向字节流的连接,发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。所以它比较适合用来发送信息量大的数据文件,或对数据完整性要求较高的文件,如压缩文件、视频文件等
而数据报套接字是基于UDP/IP协议实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能会丢失、复制或错乱到达,UDP不是一个可靠的协议,但是它的速度比较高。所以它比较适合发送一些对实时性要求较高,但是对安全性和完整性要求不太高的数据。如我们熟悉的聊天信息,即使有一点的丢失也不会造成理解上的大的问题。RFID管理系统集成商 RFID中间件 条码系统中间层 物联网软件集成