嵌入式软件设计套接字(代码实现客户端与服务端通信)

套接字:

进程间通信的方法:可以在同一台机器或者网络上不同计算机上的进行通信,明确区分客户机和服务器。
对管道概念的扩展。

服务器端:
  1. 首先服务器 应用程序通过socket系统调用创建一个套接字,他是系统分配给该服务器进程的类似文件描述符的资源,不能和其他进程分享。

  2. 其次,服务器进程使用bind系统调用给套接字命名:

    • 本地套接字的名字是linux文件系统的文件名, 一般将其放在/tmp或者/usr/tmp目录下

    • 网络套接字的名字是与客户相连的特定网络有关的服务 标识符,此标识符允许 linux将进入的针对特定端口号的连接转到正确的服务器进程

  3. 接下来服务器进程开始等待客户链接到这个名字套接字,调用listen创建一个等待队列,以便来存放来自客户的进入连接

  4. 最后,服务器通过accept系统调用来接收客户端的连接,此时,会产生一个与原有的命名套接字不同的新套接字,他仅用于这个特定的客户通信,而命名套接字则被保留下来继续处理来自其他客户的连接

客户端:
  1. 调用socket创建一个未命名的套接字,将服务器的明明套接字作为一个地址来调用connect与服务器建立连接。

  2. 一旦建立连接,就可以想使用底层文件描述符那样来用套接字进行双向的数据通信。

套接字由三个属性决定:
  • 类型
  • 协议
域:
  • 指定套接字通信中使用的网络介质,包括地址格式,最常用的以下两种方式:
    • AF_INET, 即互联网络,基于IP协议, 并且每一个服务对应一个端口号,套接字地址由IP地址+端口号决定。
    • AF_UNIX,基于本地机器,底层协议使用文件输入 /输出,地址为绝对路径的文件名。
类型:
  • 一个套接字域可能有不同的通信方式, 每种通信方式有不同的特性。
  • AF_UNIX域的套接字没有通信方面的问题,因为其基于文件系统,提供了一个可靠的双向通信通路。
  • 在AF_INET域中,需要注意底层网络特性:
    • 流套接字:由类型SOCK——STREAM指定, 基于TCP/I实现,提供一个有序、可靠、双向字节流的连接,发送的数据不会丢失、乱序、重复。大的消息会被分块、传输、重组,很像一个文件流。
    • 数据报套接字:由SOCK_STREAM指定, 基于UDP/IP协议,不建立和维持可靠连接,开销小,服务器崩溃时不需要客户端重启,因为基于 数据报的服务器不保留连接信息。
协议:
  • 讨论的重点为网络套接字不需要选择特定的协议,只要默认为0就可以。

套接字举例:

创建套接字:
/*socket系统调用创建一个套接字,并返回一个描述符,该描述符可以用来访 问这个套接字。创建的套接字是一条通信链路的一个端点。*/
#include <sys/types.h> 
#include <sys/socket.h> 
int socket( int domain, int type, int protocol);
//参数解释 
domain : 指定域
type : 指定套接字的通信类型
protocol : 指定使用协议

功能描述:
  • 客户端程序:创建一个未命名的套接字,然后把他连接到服务器套接字server_socket上,向服务器写一个字符,再读回经服务器处理后的一个字符。

  • 服务器端程序:首先创建一个服务器套接字,绑定到一个名字,然后创建一个监听队列,接收来自客户端程序的连接。

  • 服务端程序
//服务端程序
#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <sys/un.h> 
#include <unistd.h>
int main() { 
    int server_sockfd, client_sockfd; 
    int server_len, client_len; 
    struct sockaddr_un server_address; 
    struct sockaddr_un client_address;              
    unlink("server_socket"); server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);                             server_address.sun_family = AF_UNIX; 
    strcpy(server_address.sun_path, "server_socket"); 
    server_len = sizeof(server_address); 
    bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 
    listen(server_sockfd, 5); 
    while(1) { 
        char ch; printf("server waiting\n"); 
        client_len = sizeof(client_address); 
        client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_address, &client_len);        
        read(client_sockfd, &ch, 1); ch++; 
        write(client_sockfd, &ch, 1); 
        close(client_sockfd); 
    } 
} //主函数结束 
  • 客户端程序
//客户端程序
#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <sys/un.h> 
#include <unistd.h> 
int main() { 
    int sockfd; int len; 
    struct sockaddr_un address; 
    int result; 
    char ch = 'A'; 
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 
    address.sun_family = AF_UNIX; 
    strcpy(address.sun_path, "server_socket"); 
    len = sizeof(address); 
    result = connect(sockfd, (struct sockaddr *)&address, len); 
    if(result == -1) { 
        perror("oops: client1"); 
        exit(1); 
    } 
    write(sockfd, &ch, 1); 
    read(sockfd, &ch, 1); 
    printf("char from server = %c\n", ch); 
    close(sockfd); 
    exit(0);
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjxbless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值