C语言 TCP服务端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
void *read_msg(void *arg);
void *read_msg(void *arg)
{
    int fbap=*((int*)arg);
    char msg[1024];
    while (1)
    {
        memset(msg, 0, sizeof(msg));
        read(fbap,msg,sizeof(msg));
        printf("客户端收到消息:%s\n",msg);
    }
}
int main(int argc, char const *argv[])
{
    // 1、创建socket
    int fb = socket(AF_INET, SOCK_STREAM, 0);
    if (fb < 0)
    {
        perror("socket");
        return 0;
    }

    struct sockaddr_in addr;                           // 定义结构体
    addr.sin_family = AF_INET;                         // 设置为IPV4
    addr.sin_port = htons(8881);                       // 设置端口号为8080  htons():将本地网络字序改为网络传输统一的大端存储的字序
                                                       // ntohs() 将网络字序转化为本地主机字序
    addr.sin_addr.s_addr = inet_addr("192.168.1.2"); // 设置网络IP    inet_addr():将字符串转化为整型地址
     // 2、绑定socket
    if (bind(fb, (struct sockaddr *)&addr, sizeof(addr)))
    {
        perror("bind");
    }
    // 3、设置监听,,模式
    if (listen(fb, 3))
    {
        perror("listen");
    }
    // 4、接收请求
    struct sockaddr_in cli_addr;
    socklen_t len = sizeof(cli_addr);
    int fbap = accept(fb, (struct sockaddr *)(&cli_addr), &len);
    if (fbap < 0)
    {
        perror("accept");
    }
    printf("fbap=%d\n", fbap);
    printf("ntohs(cli_addr.sin_port)=%d\n", ntohs(cli_addr.sin_port));
    printf(" inet_ntoa(cli_addr.sin_addr)=%s\n", inet_ntoa(cli_addr.sin_addr));
    pthread_t id;
    pthread_create(&id, NULL, read_msg, &fbap);

    char msg[1024];
    while (1)
    {
        memset(msg, 0, sizeof(msg));
        printf("请输入客户端消息\n");
        scanf("%s",msg);
        if (strcmp(msg,"exit")==0)
        {
            break;
        }
        
        write(fbap,msg,strlen(msg));
    }
    close(fb);
    close(fbap);
    return 0;
}

步骤:

               1、创建TCPsocket

                2,绑定服务器socket

                3、设置监听模式

                4、接收请求

                5,通信(read/write)

                6、关闭通信

C语言 TCP服务端_第1张图片

 

服务端接收请求的原理:

                每接到一个请求就会分配一个文件描述符,然后就当文件I/O即可。所以可以实现多端同时通信。

涉及核心API

        1、socket()

NAME
       socket - create an endpoint for communication

SYNOPSIS
       #include          /* See NOTES */
       #include

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

功能:

        申请一个套接字;

参数:

                int domain :IP协议     IPV4——AF_INET                IPv4 Internet protocols 

                                                IPV6——AF_INET6             IPv6 Internet protocols

                int type :通信协议   UDP   SOCK_DGRAM

                                                  TCP   SOCK_STREAM  

               protocol :说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此,socket()系统调用实际上指定了相关五元组中的“协议”这一元。

返回值:

                成功:返回一个socketfb,其本质类似于一个文件描述符,相当于打开一个文件一样,是一个大于2的整数。

                失败:返回-1;

        2、bind()

功能:

        绑定服务器套接字以及IP信息、端口等数据;

   NAME             

       bind - bind a name to a socket

SYNOPSIS
       #include          /* See NOTES */
       #include

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

参数:

        int sockfb :服务端对象的fb

        const struct sockaddr *addr:              服务器地址

        socklen_t addrlen                        服务器地址长度

//------------------------------------------------------------------

    //       服务器地址原始结构体

    //        struct sockaddr

    //          {

    //            sa_family_t sa_family;                无符号短整型 16位 表示IP协议

    //            char sa_data[14];                     数据ip地址 + 端口号

    //          };

    //------------------------------------------------------------------

    //         服务器结地址结构体改良版

    //        struct sockaddr_in

    //        {

    //            sa_family_t sin_family;    无符号短整型 16位 表示IP协议 /* address family: AF_INET */

    //            in_port_t sin_port;               端口号 16位                  /* port in network byte order */

    //            struct in_addr sin_addr;          32位 IP地址      /* internet address */

    //        };

    //-------------------------------------------------------------------

    //        struct in_addr

    //        {

    //            uint32_t s_addr; /* address in network byte order */

    //        };

    //------------------------------------------------------------------

 返回值:

        成功返回:0  失败返回:-1;   

3、listen()

NAME
       listen - listen for connections on a socket

SYNOPSIS
       #include          /* See NOTES */
       #include

  int listen(int sockfd, int backlog);

功能:

                设置监听模式

参数:

        sockfd:为创建socket返回的文件描述符。

        backlog:为建立好连接处于ESTABLISHED状态的队列的长度。

返回值:

        成功:返回0;  失败:返回-1;

       RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately. 

4、accept();

NAME
       accept, accept4 - accept a connection on a socket

SYNOPSIS
       #include          /* See NOTES */
       #include

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

功能:

        接收客户端连接;

参数:

        int sockfb :服务端对象的fb

       struct sockaddr *addr :用于接收客户端连接套接字的IP端口数据结构体

        socklen_t addrlen :客户端地址长度

返回值:

              成功:返回客户端连接的sockfb;     失败返回:-1;

RETURN VALUE
       On success, these system calls return a nonnegative integer that is a file descriptor for the accepted socket.  On error, -1 is returned, and errno is  set  appropriately.

5、read/write

6、close

你可能感兴趣的:(C语言,c语言,tcp/ip,php)