Linux 本地socket通信

Linux 本地socket通信

  话不多说,直接上代码:

	//server.c
#include <sys/socket.h>
#include <sys/un.h>      // 包含本地socket的结构体
int main(){
	int srv_sockfd;

    srv_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

    struct sockaddr_un srv_addr;
    struct sockaddr_un clt_addr;

    /*note: use abstract namespace, the first bit of sun_path must been set 0*/
    bzero(&srv_addr, sizeof(srv_addr));
    srv_addr.sun_family = AF_UNIX;
    strcpy(srv_addr.sun_path, servername);
    srv_addr.sun_path[0]=0;
    int srv_len = strlen(servername)  + offsetof(struct sockaddr_un, sun_path);
    bind(srv_sockfd, (struct sockaddr*)&srv_addr, srv_len);
    listen(srv_sockfd, 1);
    int clt_len = sizeof(clt_addr);
    int clt_fd = accept(srv_sockfd,(struct sockaddr*)&clt_addr, &clt_len);
    if (clt_fd > 0)
    {
        printf("accept a connect\n");
    };
    struct iovec recvData[1];
    //char buffer[100];
    char *data = "Hello World";
    recvData[0].iov_base = (void*)malloc(strlen(data));
    recvData[0].iov_len = strlen(data);
    while (1)
    {
        if (readv(clt_fd, recvData, 1) > 0){
            printf("recvBuffer:%s, %d\n", recvData[0].iov_base, recvData[0].iov_len);
        }
        //memcpy(buffer, recvData.iov_base, recvData.iov_len);
        
    }
}
//client.c
#include <sys/socket.h>
#include <sys/un.h>      // 包含本地socket的结构体

int main()
{

    int clt_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    int clt_len;
    struct sockaddr_un client;
    client.sun_family = AF_UNIX;
    strcpy(client.sun_path, srevername);
    client.sun_path[0]=0;
    clt_len = strlen(servername)  + offsetof(struct sockaddr_un, sun_path);
    connect(clt_fd, (struct sockaddr *)&client, clt_len);
    struct iovec sendData[1];    
    char *data = "Hello World";
    sendData[0].iov_base = (void*)data;
    sendData[0].iov_len = strlen(data);
    
    while (1)
    {
        printf("SendTo:%s,%d\n", sendData[0].iov_base,strlen(data));
        writev(clt_fd, sendData, 1);
    }
}

  其中:
—— server_name为字符串,即本次建立的socket服务的名称,客户端也是通过这个名字连接服务器的。

—— 上述是采用abstract namespace,好处是不需要知道socket服务的具体路径,可以通过名称(server_name)直接连,但是sun_path[0]必须置0,而且在赋值前,最好用bzero对服务端的sockaddr_un srv_addr进行置0。
—— listen(srv_sockfd, 1);第二个参数表征可以允许的最大连接数量。
—— int clt_fd = accept(srv_sockfd,(struct sockaddr*)&clt_addr, &clt_len);如果此时没有客户端连接,则一直处于阻塞状态。
—— 发送和接收通过writev和readv函数实现,这里发送和接受都用的是客户端节点:clt_fd。

—— readv和writev是一一对应的,服务端不写,客户端读不到,反之亦然;服务端写一次,客户端也只能读一次,否则第二次读取会阻塞,直到服务端再次写入,反之亦然。
—— 注意writev和readv的函数参数,如readv(clt_fd, recvData, 1),第一个参数为所要进行读操作的连接标识,第二个参数为读取数据的缓冲区,第三个参数为所要读取的"struct iovec"的个数。其中"struct iovec"的成员变量iov_base为真正储存数据的缓冲区,iov_length为缓冲区长度,这里需要注意的是,默认是填满一个缓冲区才会转移到下一个缓冲区,如上边,若接收的缓冲区长度大于发送的长度,则会导致重复填充以至接收缓冲区满。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值