现在的位置: 首页 > 综合 > 正文

Socket编程实践(2)

2017年10月06日 ⁄ 综合 ⁄ 共 3026字 ⁄ 字号 评论关闭

Socket API基本编程模型

TCP客户/服务器模型 

 

 

简单echo服务器模型

 

 

Socket 基础API实践

socket函数

#include <sys/types.h>          /* See NOTES */

#include <sys/socket.h>

 

功能:创建一个套接字用于通信

原型

int socket(int domain, int type, int protocol);

参数

    domain:指定通信协议族(protocol family),常用取值AF_INET(IPv4)

    type:指定socket类型,流式套接字SOCK_STREAM,数据报套接字SOCK_DGRAM,原始套接字SOCK_RAW

    protocol :协议类型,常用取值0

 

返回值:

    成功返回非负整数, 它与文件描述符类似,我们把它称为套接口描述字,简称套接字。失败返回-1

 

bind函数

功能:绑定一个本地地址到套接字

原型

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数

    sockfd:socket函数返回的套接字

    addr:要绑定的地址

    addrlen:地址长度

 

返回值:

    成功返回0,失败返回-1

 

附-sockaddr结构

struct sockaddr
{
    sa_family_t sa_family;
    char        sa_data[14];
}

 

Sockaddr_in结构

struct sockaddr_in
{
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr
{
    uint32_t       s_addr;     /* address in network byte order */
};

in_addr定义如下:

typedef uint32_t in_addr_t;
struct in_addr
{
    in_addr_t s_addr;
};

//实践
int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd == -1)
    {
        err_exit("socket error");
    }

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8001);
    serverAddr.sin_addr.s_addr = INADDR_ANY;    //绑定本机的任意一个IP地址
    //serverAddr.sin_addr.s_addr = inet_addr("10.255.218.20");
    if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1)
    {
        err_exit("bind error");
    }
    else
    {
        cout << "Bind OK!" << endl;
    }

    return 0;
}

listen函数

    listen函数应该在调用socket和bind函数之后,调用函数accept之前调用。

SYNOPSIS

       #include <sys/types.h>          /* See NOTES */

       #include <sys/socket.h>

 

       int listen(int sockfd, int backlog);

 

DESCRIPTION

       listen() marks the socket referred to by sockfd as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept(2).

       The sockfd argument is a file descriptor that refers to a socket of type  SOCK_STREAM  or SOCK_SEQPACKET.

       The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow.  If a connection request arrives when the queue is full, the  client may  receive  an  error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at  connection succeeds.

 

返回值:

    成功:返回0; 失败:返回-1,并设置errno的值

 

Backlog说明:

    对于给定的监听套接口,内核要维护两个队列:


1、已由客户发出并到达服务器,服务器正在等待完成相应的TCP三路握手过程

2、已完成连接的队列

但是两个队列长度之和不能超过backlog



    If the backlog argument is greater than the value in  /proc/sys/net/core/somaxconn(Ubuntu 14.04 该值为128),  then it  is  silently truncated to that value; the default value in this file is 128.  In kernels before 2.4.25, this limit was a hard coded value, SOMAXCONN, with the value 128.

//bind实践
int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd == -1)
    {
        err_exit("socket error");
    }

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(8001);
    serverAddr.sin_addr.s_addr = INADDR_ANY;    //绑定本机的任意一个IP地址
    //serverAddr.sin_addr.s_addr = inet_addr("10.255.218.20");
    if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1)
    {
        err_exit("bind error");
    }

    //一旦调用了listen,则sockfd编程被动套接字:等待客户端的连接(只能接受连接,不能发送连接)
    if (listen(sockfd,SOMAXCONN) == -1)
    {
        err_exit("listen error");
    }
    else
    {
        cout << "SOMAXCONN = " << SOMAXCONN << endl;
        cout << "listen OK!" << endl;
    }

    return 0;
}

抱歉!评论已关闭.