ubuntu系统 网络socket通信和本地sock通信(抽象命名方式和普通命名方式)

来源:互联网 发布:报名系统源码 编辑:程序博客网 时间:2024/06/05 18:34

编译环境:ubuntu14.04 

对于网络通信可以使用网络socket进行通信,但是如果在同一个机器中的两个进程间,或一个进程的两个线程见,则可以使用本地socket进行通信.

这样做相比与网络socket的好处是,更稳定,更安全.

稳定:当时用socket网络通讯时,使用网络套接字.避免为黑客留下后门.安全

安全:一台机器,本地,相比与网络更安全,不会在网络通顺过程中被人截取数据.



本地socket通信(普通命名方式)

client程序:

//c_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"
int main(void)
{
    int connect_fd;
    int ret;
    char snd_buf[1024];
    int i;
    static struct sockaddr_un srv_addr;
//creat unix socket
    connect_fd=socket(PF_UNIX,SOCK_STREAM,0);
    if(connect_fd<0)
    {
        perror("cannot create communication socket");
        return 1;
    }
    srv_addr.sun_family=AF_UNIX;
    strcpy(srv_addr.sun_path,UNIX_DOMAIN);
//connect server
    ret=connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
    if(ret==-1)
    {
        perror("cannot connect to the server");
        close(connect_fd);
        return 1;
    }
    memset(snd_buf,0,1024);
    strcpy(snd_buf,"message from client\n");
//send info server
    for(i=0;i<4;i++)
        write(connect_fd,snd_buf,sizeof(snd_buf));
    close(connect_fd);
    return 0;
}


server端程序(普通命名方式)

//s_unix.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define UNIX_DOMAIN "/tmp/UNIX.domain"


/*
socket第一个参数
#define AF_LOCAL    PF_LOCAL             ->Local to host (pipes and file-domain)    UNIX 进程通信协议。
#define AF_UNIX     PF_UNIX                 ->Old BSD name for PF_LOCAL.


详细解释:http://blog.csdn.net/lee244868149/article/details/43732025


头文件:#include <unistd.h>


定义函数:int unlink(const char * pathname);
函数说明:unlink()会删除参数pathname 指定的文件. 如果该文件名为最后连接点, 但有其他进程打开了此文件, 则在所有关于此文件的文件描述词皆关闭后才会删除. 如果参数pathname 为一符号连接, 则此连接会被删除。


返回值:成功则返回0, 失败返回-1, 错误原因存于errno


错误代码:
1、EROFS 文件存在于只读文件系统内。
2、EFAULT 参数pathname 指针超出可存取内存空间。
3、ENAMETOOLONG 参数pathname 太长。
4、ENOMEM 核心内存不足。
5、ELOOP 参数pathname 有过多符号连接问题。
6、EIO I/O 存取错误。


*/

int main(void)
{
    socklen_t clt_addr_len;
    int listen_fd;
    int com_fd;
    int ret;
    int i;
    static char recv_buf[1024];
    socklen_t len;
    struct sockaddr_un clt_addr;
    struct sockaddr_un srv_addr;
    listen_fd=socket(PF_UNIX,SOCK_STREAM,0); //创建套接字,此时第一个参数可以看上面注释
    if(listen_fd<0)
    {
        perror("cannot create communication socket");
        return 1;
    }


    //set server addr_param
    srv_addr.sun_family=AF_UNIX;
    strncpy(srv_addr.sun_path,UNIX_DOMAIN,sizeof(srv_addr.sun_path)-1);
    unlink(UNIX_DOMAIN);
        
    //bind sockfd & addr
    ret=bind(listen_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
    if(ret==-1)
    {
        perror("cannot bind server socket");
        close(listen_fd);
        unlink(UNIX_DOMAIN);
        return 1;
    }
    //listen sockfd
    ret=listen(listen_fd,1);
    if(ret==-1)
    {
        perror("cannot listen the client connect request");
        close(listen_fd);
        unlink(UNIX_DOMAIN);
        return 1;
    }
    //have connect request use accept
    len=sizeof(clt_addr);
    com_fd=accept(listen_fd,(struct sockaddr*)&clt_addr,&len);
    if(com_fd<0)
    {
        perror("cannot accept client connect request");
        close(listen_fd);
        unlink(UNIX_DOMAIN);
        return 1;
    }
    //read and printf sent client info
    printf("\n=====info=====\n");
    for(i=0;i<4;i++)
    {
        memset(recv_buf,0,1024);
        int num=read(com_fd,recv_buf,sizeof(recv_buf));
        printf("Message from client (%d)) :%s\n",num,recv_buf);
    }
    close(com_fd);
    close(listen_fd);
    unlink(UNIX_DOMAIN);
    return 0;
}


普通命名方式会在本地产生文件,对于不想在本地产生文件的需求的话,可以使用抽象命名方式.

如下:

server代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
#include <stddef.h> // 抽象命名方式


#define SERVER_NAME "@socket_server" //抽象命名方式


int main()
{
    int sockfd,newfd,ret,recv_num = 0,recv_num_total=0;
    int recv_num1 = 0;
    char buf[50] = {0};
    char buf1[50] = {0};
    struct sockaddr_un server_addr;
    remove(SERVER_NAME);/*不管有没有,先删除一下,否则如果该文件已经存在的的话,bind会失败。*/
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sun_family=AF_UNIX;
    // strcpy(server_addr.sun_path,SERVER_NAME);
    strcpy(server_addr.sun_path, SERVER_NAME); //抽象命名方式
    server_addr.sun_path[0]=0;
    int server_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
    
    
    sockfd=socket(AF_UNIX,SOCK_STREAM,0);
    if (sockfd<0)
    {
        printf("调用socket函数建立socket描述符出错!\n");
         exit(1);
    }
    printf("调用socket函数建立socket描述符成功!\n");
    ret=bind(sockfd,(struct sockaddr *)(&server_addr), server_len);//sizeof(server_addr));
    if (ret<0)
    {
        printf("调用bind函数绑定套接字与地址出错!\n");
         exit(2);
    }
    printf("调用bind函数绑定套接字与地址成功!\n");
    ret=listen(sockfd,4);
    if (ret<0)
    {
        printf("调用listen函数出错,无法宣告服务器已经可以接受连接!\n");
         exit(3);
    }
    printf("调用listen函数成功,宣告服务器已经可以接受连接请求!\n");
    newfd=accept(sockfd,NULL,NULL);/*newfd连接到调用connect的客户端*/
    if (newfd<0)
    {
        printf("调用accept函数出错,无法接受连接请求,建立连接失败!\n");
         exit(4);
    }
    printf("调用accept函数成功,服务器与客户端建立连接成功!\n");
    while (1)
    {
        recv_num=recv(newfd,buf,10,0);
        recv_num1=recv(newfd,buf1,31,0);
        if (recv_num<0)
            printf("调用recv接受失败!\n");
        else
        {
            recv_num_total+=recv_num;
            //printf("调用recv函数成功,本次接受到%d个字节,内容为:%s。共受到%d个字节的数据。\n",recv_num,buf,recv_num_total);
            printf("recv data0: %s. recv data len0 %d\n", buf, recv_num);
            printf("recv data1: %s. recv data len1 %d", buf1, recv_num1);
        }
        sleep(2);
        break;
    }
}


client代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
#include <stddef.h> // 抽象命名方式


#define SERVER_NAME "@socket_server" //抽象命名方式


/*


程序里包含服务端和客户端两个程序,它们之间使用 AF_UNIX 实现本机数据流通信。使用 AF_UNIX 域实际上是使用本地 socket 文件来通信。
*/


int main()
{
    int sockfd,ret,send_num,send_num_total=0;
    char buf[]="this is my socket data.11111111111111111";
    printf("size:%d", (int)sizeof(buf));
    struct sockaddr_un server_addr;
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sun_family=AF_UNIX;
    // strcpy(server_addr.sun_path,"test.socket");
    strcpy(server_addr.sun_path, SERVER_NAME); //抽象命名方式
    server_addr.sun_path[0]=0;
    int client_len = strlen(SERVER_NAME) + offsetof(struct sockaddr_un, sun_path);
    
    sockfd=socket(AF_UNIX,SOCK_STREAM,0);
    if (sockfd<0)
    {
        printf("调用socket函数建立socket描述符出错!\n");
        exit(1);
    }
    printf("调用socket函数建立socket描述符成功!\n");
    ret=connect(sockfd,(struct sockaddr *)(&server_addr),client_len);//sizeof(server_addr));
    if (ret<0)
    {
        printf("调用connect函数失败,客户端连接服务器失败!\n ");
        exit(2);
    }
    printf("调用connect函数成功,客户端连接服务器成功!\n");
    while (1)
    {
        send_num=send(sockfd,buf,sizeof(buf),MSG_DONTWAIT);
        if (send_num<0)
            printf("调用send函数失败!");
        else
        {
            send_num_total+=send_num;
            printf("调用send函数成功,本次发送%d个字节,内容为:%s。目前共发送了%d个字节的数据。\n",send_num,buf,send_num_total);
        }
        sleep(2);
        break;
    }
}


关于网络socket通信,没有测试,仿照本地socket写即可,将参数换一下.提供参考如下

server代码:

   #define LOCAL_ADDRESS  "127.0.0.1"

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = inet_addr(LOCAL_ADDRESS);
    server_address.sin_port = htons(6000);
    server_len = sizeof(server_address);


    s_cmd_server_sockfd = socket(AF_INET,SOCK_STREAM,0);


    bind(s_cmd_server_sockfd,(struct sockaddr *)&server_address,server_len);


    listen(s_cmd_server_sockfd,5);
    printf("server waiting for connect\n");


    client_len = sizeof(client_address);
    s_cmd_client_sockfd = accept(s_cmd_server_sockfd,(struct sockaddr *)&client_address,(socklen_t *)&client_len);


    printf("accept cmd serverId: %d, clientid: %d\n", s_cmd_server_sockfd, s_cmd_client_sockfd);
    unsigned char buf[50];


    // while (1) {
        recv_num_cmd = recv(s_cmd_client_sockfd,buf,50,0);
        if (recv_num_cmd<0)
            printf("调用recv接受失败!\n");
        else
        {
            recv_num_total_cmd += recv_num_cmd;
            printf("cmd 调用recv函数成功,本次接受到%d个字节,内容为:\"%s\"。共受到%d个字节的数据。\n",recv_num_cmd,buf,recv_num_total_cmd);
        }
        sleep(2);


    // }


client代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <string.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>


int main()
{
    int sockfd,send_num,send_num_total=0;
    char buf[]="liushuanpeng.";


    sockaddr_in m_addr;


    int m_sock = socket ( AF_INET, SOCK_STREAM, 0 );


    if (sockfd<0)
    {
        printf("调用socket函数建立socket描述符出错!\n");
        exit(1);
    }
    printf("调用socket函数建立socket描述符成功!\n");


    m_addr.sin_family = AF_INET;
    m_addr.sin_port = htons ( 6000 );


    int status = inet_pton ( AF_INET, "127.0.0.1"/*host.c_str()*/, &m_addr.sin_addr );
    status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );


    if (status != 0)
    {
        printf("调用connect函数失败,客户端连接服务器失败!\n ");
        exit(2);
    }
    printf("cmd 调用connect函数成功,客户端连接服务器成功!\n");
    // while (1)
    // {
        //send_num=send(sockfd,buf,sizeof(buf),MSG_DONTWAIT);
        send_num = ::send(m_sock, buf, 50, MSG_NOSIGNAL);
        if (send_num<0)
            printf("调用send函数失败!");
        else
        {
            send_num_total+=send_num;
            printf("cmd 调用send函数成功,本次发送%d个字节,内容为:\"%s\"。目前共发送了%d个字节的数据。\n",send_num,buf,send_num_total);
        }
        sleep(2);
    // }
}

参考文章:

http://blog.csdn.net/shanzhizi/article/details/16882087

http://blog.csdn.net/shanzhizi/article/details/16882087

http://blog.csdn.net/qq_28839293/article/details/51276550

原创粉丝点击