网络套接字和本地套接字

socket网络编程
网络套接字和本地套接字_第1张图片

1:网络套接字
创建套接字,返回值就是套接字的文件描述符

int socket(int domain,int type,int protocol);//创建一个套接字
//domain(域):确定通信的特性,如AF_INET--IPv4,AF_INET6--IPv6,AF_UNIX--UNIX
//type:确定套接字类型,如SOCKET_STREAM(流式套接字),SOCKET_SEQPACKET(报文传递)
//protocol:确定type下的特定协议,一般用0,表示默认协议,TCP,UDP
将套接字与地址关联
    bind(int sockfd,const struct sockaddr* addr,socklen_t len);
    //sockfd:由socket返回的套接字的文件描述符
    //addr:地址信息
    //len:地址长度

设置监听

int listen(int  sockfd, int  backlog);//socfd套接字文件描述符,backlog,正在请求建立连接的最大数量

等待连接

int accept(int sockfd, void *addr, int *addrlen);
//sockfd:socket()创建的文件描述符
//addr,用来接收客户端传来的地址等基本信息
//addrlen:addr长度

客户端请求建立连接

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
//sockfd:客户端的socket()创建的文件描述符
//serv_addr:保存这目的端口和ip等服务器基本信息
//addrlen:serv_addr长度

断开连接(二选一)

close(sockfd);//关闭套接字,进入四次挥手阶段,只是断开当前进程和socket的连接
int shutdown(int sockfd, int how);//端口所有socket连接

2:本地套接字
UNIX域套接字
UNIX域套接字用于同一台计算机上运行的进程之间的通信。他的执行效率更高,仅仅是复制数据,并不执行协议处理,不需要添加和删除网络报头,不需要计算校验和等
只支持流式和数据报两种接口,服务是可靠的,不会丢失报文也不会出错,

创建套接字
这里不用UDP和TCP

int socket(int domain,int type,int protocol);//创建一个套接字
//domain(域):AF_UNIX--UNIX
//type:确定套接字类型,如SOCKET_STREAM(流式套接字),SOCKET_SEQPACKET(报文传递)(其实这个参数并没有用。这里只是占了个位置)
//protocol:确定type下的特定协议

bind 绑定定函数:

unlink(path)//确保之前path文件不存在,bind会创建该文件。。。如果存在这个文件不unlinkbind会失败
int bind(int socket, const struct sockaddr *address, size_t address_len);

sockaddr 此处是

struct sockaddr_un {  
    sa_family_t sun_family;  //AF_UNIX
    char sun_path[108];  //表示本地文件路径名,(可以为相对路径也可以为绝对路径) 分为两种一个是普通路径名(linux文件路径)必须以NULL('\0')结尾,
}  

客户端请求建立连接

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
//sockfd:客户端的socket()创建的文件描述符
//serv_addr:保存服务器sun_path
//addrlen:serv_addr长度

服务器

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "wrap.h"

#define SERV_ADDR  "serv.socket"

int main(void)
{
    int lfd, cfd, len, size, i;
    struct sockaddr_un servaddr, cliaddr;
    char buf[4096];

    lfd = Socket(AF_UNIX, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path,SERV_ADDR);

    len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);     /* servaddr total len */

    unlink(SERV_ADDR);                              /* 确保bind之前serv.sock文件不存在,bind会创建该文件 */
    Bind(lfd, (struct sockaddr *)&servaddr, len);           /* 参3不能是sizeof(servaddr) */

    Listen(lfd, 20);

    printf("Accept ...\n");
    while (1) {
        len = sizeof(cliaddr);
        cfd = Accept(lfd, (struct sockaddr *)&cliaddr, (socklen_t *)&len);

        len -= offsetof(struct sockaddr_un, sun_path);      /* 得到文件名的长度 */
        cliaddr.sun_path[len] = '\0';                       /* 确保打印时,没有乱码出现 */

        printf("client bind filename %s\n", cliaddr.sun_path);

        while ((size = read(cfd, buf, sizeof(buf))) > 0) {
            for (i = 0; i < size; i++)
                buf[i] = toupper(buf[i]);
            write(cfd, buf, size);
        }
        close(cfd);
    }
    close(lfd);

    return 0;
}

客户端

#include 
#include 
#include          
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "wrap.h"

#define SERV_ADDR "serv.socket"
#define CLIE_ADDR "clie.socket"

int main(void)
{
    int  cfd, len;
    struct sockaddr_un servaddr, cliaddr;
    char buf[4096];

    cfd = Socket(AF_UNIX, SOCK_STREAM, 0);

    bzero(&cliaddr, sizeof(cliaddr));
    cliaddr.sun_family = AF_UNIX;
    strcpy(cliaddr.sun_path,CLIE_ADDR);

    len = offsetof(struct sockaddr_un, sun_path) + strlen(cliaddr.sun_path);     /* 计算客户端地址结构有效长度 */

    unlink(CLIE_ADDR);
    Bind(cfd, (struct sockaddr *)&cliaddr, len);                                 /* 客户端也需要bind, 不能依赖自动绑定*/


    bzero(&servaddr, sizeof(servaddr));                                          /* 构造server 地址 */
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path,SERV_ADDR);

    len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);   /* 计算服务器端地址结构有效长度 */

    Connect(cfd, (struct sockaddr *)&servaddr, len);

    while (fgets(buf, sizeof(buf), stdin) != NULL) {
        write(cfd, buf, strlen(buf));
        len = read(cfd, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, len);
    }

    close(cfd);

    return 0;
}
//注:clie.socket ,serv.socket是socket伪文件,相当于管道,实际不占空间

你可能感兴趣的:(计算机网络)