简介 Socket

在Unix/Linux中,为了统一各种硬件的操作,简化接口,不同的硬件设备都被看作为一个文件,对于这些文件的操作就相当于对磁盘上普通文件的操作。
Unix/Linux中的一切都是文件

为了区分已打开的文件,Unix/Linux会给每个文件分配一个整数ID(文件描述符),所以网络链接也是一个文件,同样拥有文件描述符
通过socket()创建一个网络连接,其返回值就是一个文件描述符。

   //1.sockf就是socket返回的文件描述符
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        perror("socket");
        exit(-1);
    }

当sock()成功执行之后,使用bind()将套接字与ip::port绑定起来,客户端使用connect()建立链接

//服务器端
    struct sockaddr_in sock_addr;
    bzero(&sock_addr, sizeof(sock_addr));	  // 清空
    sock_addr.sin_family = AF_INET;		  // IPv4
    sock_addr.sin_port   = htons(port);	  // 端口
    sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip

    //2.绑定
    int err_status = bind(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
    if(err_status != 0)
    {
        perror("binding");
        close(sockfd);
        exit(-1);
    }

//客户端
    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);

    if (connect(client_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))==-1)
    {
        /* code */
        printf("server connection error!\n");
        return -1;
    }

使用listen()让套接字进入被动监听状态,再调用accept()相应客户端请求

    /3.监听,套接字变被动
    err_status = listen(sockfd, 10);
    if(err_status != 0)
    {
        perror("listen");
        close(sockfd);
        exit(-1);
    }

    while(1)
    {
       char client_ip[INET_ADDRSTRLEN] = {0};
       struct sockaddr_in client_addr;
       socklen_t cliaddr_len = sizeof(client_addr);

        // 取出已完成的连接
        int connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);
	if(connfd < 0)
        {
            perror("accept");
            close(sockfd);
            exit(-1);
        }

     }

使用fork()创建子进程接受客户端消息

	pid_t pid = fork();
        if(pid < 0){
            perror("fork");
            exit(-1);
        }else if(0 == pid){
            //子进程 接收客户端的信息
            close(sockfd);   // 关闭监听套接字
            char recv_buf[1024] = {0};
            int recv_len = 0;
            memset(client_ip, 0, sizeof(client_ip)); // 清空
            inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
            printf("----------------------------------------------\n");
            printf("client ip=%s,port=%d\n", client_ip, ntohs(client_addr.sin_port));

            // 接收数据
            while( (recv_len = recv(connfd, recv_buf, sizeof(recv_buf), 0)) > 0 )
            {
                printf("recv_buf: %s\n", recv_buf); // 打印数据
                send(connfd, recv_buf, recv_len, 0); // 给客户端回数据
            }

            printf("client_port %d closed!\n", ntohs(client_addr.sin_port));
            close(connfd);    //关闭已连接套接字
            exit(0);

        }
        else if(pid > 0){	// 父进程
            close(connfd);    //关闭已连接套接字
        }	

Q.E.D.


一个追风车的傻子