socket编程(二)

来源:互联网 发布:ug nx8.0数控编程教程 编辑:程序博客网 时间:2024/06/05 19:03

TCP客户/服务器模型

一个典型的TCP客户/服务器模型流程如下:
这里写图片描述

回射客户/服务器

这里写图片描述
1. 客户端从标准输入获取一行数据,然后发送到服务器;
2. 服务器收到信息后,不处理消息内容,直接将消息内容原封不动地发送给客户端;
3. 客户端收到后,在标准输出上打印出来。

socket、bind、listen、accept、connect

socket函数

  • 包含头文件<sys/socket.h>
  • 功能:创建一个套接字用于通信
  • 原型
    • int socket(int domain, int type, int protocol);
  • 参数
    • domain: 指定通信协议族(protocol family)
    • type: 指定socket类型,流式套接字SOCK_STREAM, 数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW
    • protocol:协议类型
  • 返回值:成功返回非负整数,它与文件描述符类似,我们把它们称为套接口描述字,简称套接字。失败返回-1

bind函数

  • 包含头文件<sys/socket.h>
  • 功能:绑定一个本地地址到套接字
  • 原型:
    • int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
  • 参数
    • sockfd:socket函数返回的套接字
    • addr:要绑定的地址
    • addrlen:地址长度
  • 返回值:成功放回0,失败返回-1

listen函数

  • 包含头文件<sys/socket.h>
  • 功能:将套接字用于监听进入的连接
  • 原型:
    • int listen(int sockfd, int backlog);
  • 参数:
    • sockfd:socket函数返回的套接字
    • backlog:规定内核为此排队的最大连接个数
  • 返回值:成功返回0,失败返回-1
  • 一般来说,listen应该socketbind函数之后,函数accept之前调用
  • 对于给定的监听套接口,要维护两个队列
    • 1、已由并到达服务器,服务器正在等待完成相应的TCP三次握手过程
    • 2、已完成连接的队列
    • 两队列之和不超过backlog

一旦调用listen函数后,该套接字便成了被动套接字,否则默认为主动套接字。

主动套接字 用于发起连接,会调用connect函数来发起连接 被动套接字 用于接受连接,会调用accept函数来接受连接

accept函数

  • 包含头文件<sys/socket.h>
  • 功能:从已完成连接的队列返回第一个,如果已完成连接队列为空,则阻塞
  • 原型
    • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 参数:
    • sockfd:服务器套接字
    • addr:将返回对等方的套接字地址(也就是将对方的地址存储于addr指向的结构体中)
    • addrlen:返回对等方套接字地址长度(也就是将对方的地址长度存储于addrlen指向的区域中,addrlen所指的区域一定要有初始值,否则accept会失败)
  • 返回值:成功返回非负整数(一个已连接套接字(这个套接字不是被动套接字,而是一个主动套接字)),失败返回-1

connect函数

  • 包含头文件<sys/socket.h>
  • 功能:建立一个addr所指定的套接字
  • 原型
    • int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 参数
    • sockfd:未连接套接字
    • addr:要连接的套接字地址
    • addrlen:第二个参数addr长度
  • 返回值:成功返回0,失败返回-1

TCP回射客户/服务器程序

服务器端

/*************************************************************************    > File Name: echoserv.c    > Author: Marvin    > Mail: czwwonder4@outlook.com     > Created Time: Thu Jun 29 14:27:59 2017 ************************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/types.h>#include <unistd.h>#include <errno.h>int main(){    int listenfd;    //创建一个套接字    if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){        perror("Create socket failed.");        exit(1);    }    /*int socket(int domain, int type, int protocol);*/    struct sockaddr_in servaddr;    memset(&servaddr, 0, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(9000);    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    /*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/    /*inet_aton("127.0.0.1", &servaddr.sin_addr);*/    //绑定套接字到相应地址    if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){        perror("bind error.");        exit(1);    }    //监听    if(listen(listenfd, SOMAXCONN) < 0){        perror("listen() error.");        exit(1);    }    struct sockaddr_in peeraddr;    socklen_t peerlen = sizeof(peeraddr);    int conn;//    char recvbuf[1024];    //接收客户端连接,客户地址信息存放在peeraddr中    if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0){        perror("accept() error.");        exit(1);    }    while (1){        memset(recvbuf, 0, sizeof(recvbuf));        int ret = read(conn, recvbuf, sizeof(recvbuf));接收客户端消息        fputs (recvbuf, stdout);        write(conn, recvbuf, ret);//发送消息给客户端    }    close(conn);//关闭连接    close(listenfd);//关闭监听    return 0;}

客户端

/*************************************************************************    > File Name: echoclient.c    > Author: Marvin    > Mail: czwwonder4@outlook.com     > Created Time: Thu Jun 29 14:27:59 2017 ************************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/types.h>#include <unistd.h>#include <errno.h>int main(){    int sock;    //创建一个套接字    if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){        perror("Creat socket failed.");        exit(1);    }    /*int socket(int domain, int type, int protocol);*/    struct sockaddr_in servaddr;    memset(&servaddr, 0, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(9000);    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");    /*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/    /*inet_aton("127.0.0.1", &servaddr.sin_addr);*/    if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){        perror("connect() error");        exit(1);    }    char sendbuf[1024] = {0};    char recvbuf[1024] = {0};    while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){        write(sock, sendbuf, strlen(sendbuf));        read(sock, recvbuf, sizeof(recvbuf));        memset(&sendbuf, 0, sizeof(sendbuf));        fputs(recvbuf, stdout);        memset(&recvbuf, 0, sizeof(recvbuf));    }    close(sock);    return 0;}

演示结果
这里写图片描述

原创粉丝点击