Linux下TCP开发

Linux TCP开发(服务器):


1、通过socket()函数实现创建套接字。
2、往sockaddr_in结构体中,填充对方的地址信息。
3、通过bind函数,绑定自己设备信息(上一步的sockaddr_in结构体)。
4、通过listen()函数,将该套接字和套接字对应的连接队列长度告诉 Linux 内核。
4、通过accept()函数,从处于 established 状态的连接队列头部取出一个已经完成的连接,如果这个队列没有已经完成的连接,accept()函数就会阻塞,直到取出队列中已完成的用户连接为止。
5、通过recv()接收数据。
6、通过send()发送数据。

TCP的服务端代码建立:


{
    int listenfd, connfd;
    struct sockaddr_in myaddr;

    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("fail to socket");
        exit(-1);
    }

    bzero(&myaddr, sizeof(myaddr));
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);
    if (bind(listenfd, (SA *)&myaddr, sizeof(myaddr)) < 0)
    {
        perror("fail to bind");
        exit(-1);
    }

    if (listen(listenfd, 5) < 0)
    //第二个参数(backlog)的作用:告诉内核连接队列的长度。
    //内核为任何一个给定的监听套接口维护两个队列:
    //1、未完成连接队列(incomplete connection queue),每个这样的 SYN 分节对应其中一项:已由某个客户发出并到达服务器,而服务器正在等待完成相应的 TCP 三次握手过程。这些套接口处于 SYN_RCVD 状态。
    //2、已完成连接队列(completed connection queue),每个已完成 TCP 三次握手过程的客户对应其中一项。这些套接口处于 ESTABLISHED 状态。
    //一般此参数填写5

    {
        perror("fail to listen");
        exit(-1);
    }

    while (1)
    {
        if ((connfd = accept(listenfd, NULL, NULL)) < 0)
        //从处于 established 状态的连接队列头部取出一个已经完成的连接,如果这个队列没有已经完成的连接,accept()函数就会阻塞,直到取出队列中已完成的用户连接为止。
        //参数一:利用系统调用socket()建立的套接字描述符,通过bind()绑定到一个本地地址(一般为服务器的套接字),并且通过listen()一直在监听连接;
        //参数二:服务器等套接字的地址
        //参数三:套接字长度

        {
            perror("fail to accept");
            exit(-1);
        }
        
        close(connfd);
    }
    return 0;
}

TCP的客户端代码建立:


{
    //设置一个socket地址结构client_addr,代表客户机internet地址, 端口
    struct sockaddr_in client_addr;
    bzero(&client_addr, sizeof(client_addr));        //把一段内存区的内容全部设置为0
    client_addr.sin_family = AF_INET;                //internet协议族
    client_addr.sin_addr.s_addr = htons(INADDR_ANY); //INADDR_ANY表示自动获取本机地址
    client_addr.sin_port = htons(0);                 //0表示让系统自动分配一个空闲端口
    //创建用于internet的流协议(TCP)socket,用client_socket代表客户机socket
    int client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket < 0)
    {
        exit(1);
    }
    //把客户机的socket和客户机的socket地址结构联系起来
    if (bind(client_socket, (struct sockaddr *)&client_addr, sizeof(client_addr)))
    {
        exit(1);
    }

    //设置一个socket地址结构server_addr,代表服务器的internet地址, 端口
    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    if (inet_aton(server_ip, &server_addr.sin_addr) == 0) //服务器的IP地址来自程序的参数
    {
        exit(1);
    }
    server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
    socklen_t server_addr_length = sizeof(server_addr);
    //向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接
    if (connect(client_socket, (struct sockaddr *)&server_addr, server_addr_length) < 0)
    {
        exit(1);
    }
    return client_socket;
}

TCP的发送:


send(client_socket, buffer, len, 0);

 

TCP的接收:


    length = recv(socket_id, buffer, BUFFER_SIZE, 0);
    if (length > 0)
    {
        msgarrvd(buffer);
        bzero(buffer, BUFFER_SIZE);
    }

你可能感兴趣的:(linux)