socket编程-TCP开发常用函数

测试用例

1、网络字节序与主机字节序转换

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>

int main(int argc, char const *argv[])
{
    //声明两个端口号
    unsigned short local_num=0x1f,network_num=0;

    network_num = htons(0x1f);
    printf("将主机字节序无符号整数0x%hx转化为网络字节序0x%hx\n",local_num,network_num);
    local_num=ntohs(network_num);
    printf("将网络字节序无符号整数0x%hx转化为主机字节序0x%hx\n",network_num,local_num);

    return 0;
}

makefile

cpp 复制代码
CC := gcc
num_endianess_convert:num_endianess_convert.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@ 

2、网络地址填写案例

cpp 复制代码
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>

int main(int argc, char const *argv[])
{
    printf("192.168.6.101的16进制表示为 0x%X 0x%X 0x%X 0x%X \n",192,168,6,101);
    //声明结构体接收数据
    struct sockaddr_in server_addr;
    struct in_addr server_in_addr;
    in_addr_t server_in_addr_t ;
    memset(&server_addr,0,sizeof(server_addr));
    memset(&server_in_addr,0,sizeof(server_in_addr));
    memset(&server_in_addr_t,0,sizeof(server_in_addr_t));
    
    //不推荐使用 错误返回-1->表示一个正常可用的输出 255.255.255.255
    server_in_addr_t = inet_addr("192.168.6.101");
    printf("inet_addr:0x%X\n",server_in_addr_t);

    //推荐使用 出错返回-1 但是传入结构体的数据不是-1
    inet_aton("192.168.6.101",&server_in_addr);
    //具体只能使用ip协议
    printf("inet_aton:0x%X\n",server_in_addr.s_addr);

    //万能方法
    inet_pton(AF_INET,"192.168.6.101",&server_in_addr.s_addr);
    printf("inet_pton:0x%X\n",server_in_addr.s_addr);

    //结构体转换字符串
    printf("转化回字符串%s\n",inet_ntoa(server_in_addr));

    //本地网络地址
    printf("本地网络地址:0x%X\n",inet_lnaof(server_in_addr));
    //网络号地址
    printf("网络号地址:0x%X\n",inet_netof(server_in_addr));
    
    //拼接为完整的ip地址
    server_addr.sin_addr = inet_makeaddr(inet_netof(server_in_addr),inet_lnaof(server_in_addr));
    printf("拼接后的ip地址为:%s\n",inet_ntoa(server_addr.sin_addr));
    return 0;
}

makefile

cpp 复制代码
inet_endian_convert:inet_endian_convert.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@ 

3、

(1)服务端使用连接代码

cpp 复制代码
//single_conn_server.c内容

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>

#define handle_error(cmd,result)\
    if (result < 0)             \
    {                           \
        perror(cmd);            \
        return -1 ;             \
    }                           \

void *read_from_client(void *arg)
{
    //使用recv接收客户端发送的数据打印到控制台
    char *read_buf=NULL;
    int client_fd =*(int*)arg;
    read_buf = malloc(sizeof(char)*1024);//初始化
    ssize_t count = 0;
    if (!read_buf)
    {
        perror("malloc sever read_buf");
        return NULL;
    }
    
    //接收数据
    //只要能接收到数据 正常使用 一直挂起
    while (count = recv(client_fd,read_buf,1024,0))
    {
        if (count < 0)
        {
            perror("recv");
        }
        
        fputs(read_buf,stdout);
    }
    
    printf("客户端请求关闭\n");
    free(read_buf);
    return NULL;
}

void *write_to_client(void *arg)
{
    //接收控制台输入的信息 写出去
    char *write_buf=NULL;
    int client_fd =*(int*)arg;
    write_buf = malloc(sizeof(char)*1024);//初始化
    int count = 0;
    if (!write_buf)
    {
        perror("malloc sever write_buf");
        return NULL;
    }
    while (fgets(write_buf,1024,stdin) != NULL)
    {
        //发送数据
       count = send(client_fd,write_buf,10124,0);
       if (count < 0)
       {
            perror("send");
       }
    }
    printf("接收到控制台的关闭请求 不再写入 关闭连接\n");
    //可以具体到关闭某一端
    shutdown(client_fd,SHUT_WR);
    free(write_buf);
    return NULL;
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sockfd,tmep_result,clientfd;
    pthread_t pid_read,pid_write;

    //清空
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));
    //填写服务端地址
    server_addr.sin_family=AF_INET;
    //填写ip地址 0.0.0.0
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    //填写端口号
    server_addr.sin_port = htons(6666);
    //网络编程流程
    //1、创建socket流程
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    handle_error("socket",sockfd);
    //2、绑定地址
    tmep_result = bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
    handle_error("bind",tmep_result);
    //3、进入监听状态
    tmep_result=listen(sockfd,128);
    handle_error("listen",tmep_result);
    //4、获取客户端的连接
    socklen_t cliaddr_len = sizeof(client_addr);
    //返回i的文件描述符才是能够和客户端收发消息的文件描述符
    //如果调用accept之后没有客户端连接 这里会挂起等待
    clientfd = accept(sockfd,(struct sockaddr *)&client_addr,&cliaddr_len);
    handle_error("accept",clientfd);

    printf("与客户端%s %d建立连接 文件描述符是%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd);

    //创建子线程用于收消息
    pthread_create(&pid_read,NULL,read_from_client,(void*)&clientfd);
    //创建子线程用于发消息
    pthread_create(&pid_write,NULL,write_to_client,(void*)&clientfd);

    //阻塞主线程
    pthread_join(pid_read,NULL);
    pthread_join(pid_write,NULL);

    //释放资源
    printf("释放资源");
    close(clientfd);
    close(sockfd);

    return 0;
}

(2)客户端代码

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>

#define handle_error(cmd,result)\
    if (result < 0)             \
    {                           \
        perror(cmd);            \
        return -1;              \
    }                           \

void *read_from_server(void *arg)
{
    //使用recv接收客户端发送的数据打印到控制台
    char *read_buf=NULL;
    int client_fd =*(int*)arg;
    read_buf = malloc(sizeof(char)*1024);//初始化
    ssize_t count = 0;
    if (!read_buf)
    {
        perror("malloc sever read_buf");
        return NULL;
    }
    
    //接收数据
    //只要能接收到数据 正常使用 一直挂起
    while (count = recv(client_fd,read_buf,1024,0))
    {
        if (count < 0)
        {
            perror("recv");
        }
        
        fputs(read_buf,stdout);
    }
    
    printf("服务端请求关闭\n");
    free(read_buf);
    return NULL;
}

void *write_to_server(void *arg)
{
    //接收控制台输入的信息 写出去
    char *write_buf=NULL;
    int client_fd =*(int*)arg ;
    write_buf = malloc(sizeof(char)*1024);//初始化
    ssize_t count = 0;
    if (!write_buf)
    {
        perror("malloc sever write_buf");
        return NULL;
    }
    while (fgets(write_buf,1024,stdin) != NULL)
    {
        //发送数据
       count = send(client_fd,write_buf,10124,0);
       if (count < 0)
       {
            perror("send");
       }
    }
    printf("接收到控制台的关闭请求 不再写入 关闭连接\n");
    //可以具体到关闭某一端
    shutdown(client_fd,SHUT_WR);
    free(write_buf);
    return NULL;
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sockfd,tmep_result;
    pthread_t pid_read,pid_write;

    //清空
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));

    //填写客户端地址
    client_addr.sin_family=AF_INET;
    //填写ip地址 0.0.0.0
    inet_pton(AF_INET,"192.168.137.101",&client_addr.sin_addr);
    //填写端口号
    client_addr.sin_port = htons(8888);

    //填写服务端地址
    server_addr.sin_family=AF_INET;
    //填写ip地址 0.0.0.0
    inet_pton(AF_INET,"0.0.0.0",&server_addr.sin_addr);
    //填写端口号
    server_addr.sin_port = htons(6666);

    //客户端网络编程流程
    //1、创建socket
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    handle_error("socket",sockfd);
    //2、绑定地址
    tmep_result = bind(sockfd,(struct sockaddr *)&client_addr,sizeof(client_addr));
    handle_error("bind",tmep_result);
    //3、主动连接服务端
    tmep_result = connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));

    printf("链接上服务端 %s %d\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port));

    //创建子线程用于收消息
    pthread_create(&pid_read,NULL,read_from_server,(void*)&sockfd);
    //创建子线程用于发消息
    pthread_create(&pid_write,NULL,write_to_server,(void*)&sockfd);

    //阻塞主线程
    pthread_join(pid_read,NULL);
    pthread_join(pid_write,NULL);

    //释放资源
    printf("释放资源");
    close(sockfd);

    return 0;
}

makefile

cpp 复制代码
single_conn_server:single_conn_server.c
	-$(CC) -o $@ $^ -lpthread

single_conn_client:single_conn_client.c
	-$(CC) -o $@ $^ -lpthread

打开终端进行测试

4、缓冲机制

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>

int main(int argc, char const *argv[])
{
    //打开文件
    FILE *file = fopen("/home/lxl/socket_test/testfile.txt","w");
    if (file == NULL)
    {
        perror("fopen");
        return 1;
    }
    
    //修改刷写模式
    if (setvbuf(file,NULL,_IOLBF,0) !=0)
    {
        perror("setvbuf");
    }
    

    //文件写入是全缓冲 等待缓冲区满或手动刷写
    fprintf(file,"hello\n");
    //可以使用手动刷写
    //fflush(file);

    char *args[]={"/usr/bin/ping","-c","10","www.lxl.com",NULL};
    char*envs[]={NULL};
    execve(args[0],args,envs);
    //如果跳转失败
    perror("execve");




    return 0;
}

makefile

cpp 复制代码
without_buf_test:without_buf_test.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@ 

5、查看正在运行的TCP进程

6、安装wireshark

7、服务端基于多线程的支持多个连接的范例程序

(1)服务端代码

cpp 复制代码
//multi_conn_threads_server.c 内容
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>

#define handle_error(cmd,result)\
    if (result < 0)             \
    {                           \
        perror(cmd);            \
        return -1 ;             \
    }                           \

void * read_from_client_then_write(void * arg)
{
    //读取客户端发送过来的数据 回复收到
    int client_fd = *(int *)arg;
    char * read_buf = NULL;
    char * write_buf = NULL;
    ssize_t count = 0,send_count = 0;
    read_buf = malloc(sizeof(char)*1024);
    write_buf = malloc(sizeof(char)*1024);

    if (!read_buf)
    {
        printf("初始化读缓冲失败\n");
        close(client_fd);
        perror("read_buf");
    }
    if (!write_buf)
    {
        printf("初始化写缓冲失败\n");
        close(client_fd);
        perror("write_buf");
    }

    while (count = recv(client_fd,read_buf,1024,0))
    {
        if (count < 0)
        {
            perror("recv");
        }
        
        //接收数据打印到控制台
        printf("从%d客户端收到数据%s\n",client_fd,read_buf);
        //首先把收到的消息写到写缓存
        strcpy(write_buf,"收到\n");
        send_count = send(client_fd,write_buf,1024,0);
        if (send_count < 0)
        {
            perror("send");
        }
    }
    //当客户端输入ctrl+d时会退出
    //shutdown(client_fd,SHUT_RD);
    close(client_fd);
    free(read_buf);
    free(write_buf);
}


int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sockfd,tmep_result;

    //清空
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));
    //填写服务端地址
    server_addr.sin_family=AF_INET;
    //填写ip地址 0.0.0.0
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    //填写端口号
    server_addr.sin_port = htons(6666);
    //网络编程流程
    //1、创建socket流程
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    handle_error("socket",sockfd);
    //2、绑定地址
    tmep_result = bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
    handle_error("bind",tmep_result);
    //3、进入监听状态
    tmep_result=listen(sockfd,128);
    handle_error("listen",tmep_result);
    //4、获取客户端的连接
    //需要能够接收多个连接
    socklen_t cliaddr_len = sizeof(client_addr);
    while (1)
    {
        pthread_t pid_read_write;
        int clientfd = accept(sockfd,(struct sockaddr *)&client_addr,&cliaddr_len);
        handle_error("accept",clientfd);
        printf("与客户端%s %d 建立连接%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd);
        //和每一个客户端使用一个线程交互 把客户端发送的信息打印到控制台 回复收到
        int pcR = pthread_create(&pid_read_write,NULL,read_from_client_then_write,(void *)&clientfd);
        handle_error("pthread_create",pcR);
        //需要等待线程结束 但是不能挂起等待
        pthread_detach(pid_read_write);
        
    }
    
    printf("释放资源\n");
    close(sockfd);

    return 0;
}

(2)客户端代码

cpp 复制代码
//multi_conn_threads_client.c 内容
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>

#define handle_error(cmd,result)\
    if (result < 0)             \
    {                           \
        perror(cmd);            \
        return -1;              \
    }                           \

void *read_from_server(void *arg)
{
    //使用recv接收客户端发送的数据打印到控制台
    char *read_buf=NULL;
    int client_fd =*(int*)arg;
    read_buf = malloc(sizeof(char)*1024);//初始化
    ssize_t count = 0;
    if (!read_buf)
    {
        perror("malloc sever read_buf");
        return NULL;
    }
    
    //接收数据
    //只要能接收到数据 正常使用 一直挂起
    while (count = recv(client_fd,read_buf,1024,0))
    {
        if (count < 0)
        {
            perror("recv");
        }
        
        fputs(read_buf,stdout);
    }
    
    printf("服务端请求关闭\n");
    free(read_buf);
    return NULL;
}

void *write_to_server(void *arg)
{
    //接收控制台输入的信息 写出去
    char *write_buf=NULL;
    int client_fd =*(int*)arg ;
    write_buf = malloc(sizeof(char)*1024);//初始化
    ssize_t count = 0;
    if (!write_buf)
    {
        perror("malloc sever write_buf");
        return NULL;
    }
    while (fgets(write_buf,1024,stdin) != NULL)
    {
        //发送数据
       count = send(client_fd,write_buf,1024,0);
       if (count < 0)
       {
            perror("send");
       }
    }
    printf("接收到控制台的关闭请求 不再写入 关闭连接\n");
    //可以具体到关闭某一端
    shutdown(client_fd,SHUT_WR);
    free(write_buf);
    return NULL;
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sockfd,tmep_result;
    pthread_t pid_read,pid_write;

    //清空
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));

    

    //填写服务端地址
    server_addr.sin_family=AF_INET;
    //填写ip地址 0.0.0.0
    inet_pton(AF_INET,"0.0.0.0",&server_addr.sin_addr);
    //填写端口号
    server_addr.sin_port = htons(6666);

    //客户端网络编程流程
    //1、创建socket
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    handle_error("socket",sockfd);
    //2、绑定地址
    //客户端可以不绑定 系统会自动分配一个空闲的端口号给客户端

    //3、主动连接服务端
    tmep_result = connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));

    printf("链接上服务端 %s %d\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port));

    //创建子线程用于收消息
    pthread_create(&pid_read,NULL,read_from_server,(void*)&sockfd);
    //创建子线程用于发消息
    pthread_create(&pid_write,NULL,write_to_server,(void*)&sockfd);

    //阻塞主线程
    pthread_join(pid_read,NULL);
    pthread_join(pid_write,NULL);

    //释放资源
    printf("释放资源");
    close(sockfd);

    return 0;
}

makefle

cpp 复制代码
multi_conn_threads_server:multi_conn_threads_server.c
	-$(CC) -o $@ $^ -lpthread

multi_conn_threads_client:multi_conn_threads_client.c
	-$(CC) -o $@ $^ -lpthread

8、服务端基于多进程的支持多个连接的范例程序

(1)服务端

cpp 复制代码
//mutli_conn_processes_server.c 内容

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<sys/wait.h>
#include<signal.h>

#define handle_error(cmd,result)\
    if (result < 0)             \
    {                           \
        perror(cmd);            \
        return -1 ;             \
    }                           \

void * read_from_client_then_write(void * arg)
{
    //读取客户端发送过来的数据 回复收到
    int client_fd = *(int *)arg;
    char * read_buf = NULL;
    char * write_buf = NULL;
    ssize_t count = 0,send_count = 0;
    read_buf = malloc(sizeof(char)*1024);
    write_buf = malloc(sizeof(char)*1024);

    if (!read_buf)
    {
        printf("初始化读缓冲失败\n");
        close(client_fd);
        perror("read_buf");
    }
    if (!write_buf)
    {
        printf("初始化写缓冲失败\n");
        close(client_fd);
        perror("write_buf");
    }

    while (count = recv(client_fd,read_buf,1024,0))
    {
        if (count < 0)
        {
            perror("recv");
        }
        
        //接收数据打印到控制台
        printf("从%d客户端收到数据%s\n",client_fd,read_buf);
        //首先把收到的消息写到写缓存
        strcpy(write_buf,"收到\n");
        send_count = send(client_fd,write_buf,1024,0);
        if (send_count < 0)
        {
            perror("send");
        }
    }
    //当客户端输入ctrl+d时会退出
    //shutdown(client_fd,SHUT_RD);
    close(client_fd);
    free(read_buf);
    free(write_buf);
}

/*
关闭回收所有的子进程 避免僵尸进程
*/
void zombie_dealr(int sig)
{
    pid_t pid;
    int status;
    //一个SIGCHLD可能对应多个子进程的退出
    //使用while循环回收所有退出的子进程,避免僵尸进程的出现
    while ((pid = waitpid(-1,&status,WNOHANG) > 0))
    {
        if (WIFEXITED(status))
        {
            printf("子进程:%d 以%d状态正常退出,已被回收\n",pid,WEXITSTATUS(status));
        }
        else if(WIFSIGNALED(status))
        {
            printf("子进程:%d 被%d信号杀死,已被回收\n",pid,WTERMSIG(status));
        }
        else
        {
            printf("子进程:%d 因其他原因退出,已被回收\n",pid);
        }

    }
    
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sockfd,tmep_result;

    //注册信号处理函数 SIGCHLD
    signal(SIGCHLD,zombie_dealr);

    //清空
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));
    //填写服务端地址
    server_addr.sin_family=AF_INET;
    //填写ip地址 0.0.0.0
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    //填写端口号
    server_addr.sin_port = htons(6666);
    //网络编程流程
    //1、创建socket流程
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    handle_error("socket",sockfd);
    //2、绑定地址
    tmep_result = bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
    handle_error("bind",tmep_result);
    //3、进入监听状态
    tmep_result=listen(sockfd,128);
    handle_error("listen",tmep_result);
    //4、获取客户端的连接
    //需要能够接收多个连接
    socklen_t cliaddr_len = sizeof(client_addr);
    while (1)
    {
        pthread_t pid_read_write;
        int clientfd = accept(sockfd,(struct sockaddr *)&client_addr,&cliaddr_len);
        handle_error("accept",clientfd);
        //创建单独的子进程和连接的客户端交互
        pid_t pid =fork();
        handle_error("fork",pid);
        if (pid == 0)
        {
            //子进程
            //关闭不会使用的sockfd
            close(sockfd);
            printf("与客户端%s %d 建立连接%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd);
            //从客户端读取数据并回复
            read_from_client_then_write((void *)&clientfd);
            //关闭clientfd
            close(clientfd);
            exit(EXIT_SUCCESS);
        }
        else
        {
            //父进程
            //关闭掉不使用的clientfd
            close(clientfd);
        }
    }
    
    printf("释放资源\n");
    close(sockfd);

    return 0;
}

(2)客户端

cpp 复制代码
//multi_conn_processes_client.c 内容

#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>

#define handle_error(cmd,result)\
    if (result < 0)             \
    {                           \
        perror(cmd);            \
        return -1;              \
    }                           \

void *read_from_server(void *arg)
{
    //使用recv接收客户端发送的数据打印到控制台
    char *read_buf=NULL;
    int client_fd =*(int*)arg;
    read_buf = malloc(sizeof(char)*1024);//初始化
    ssize_t count = 0;
    if (!read_buf)
    {
        perror("malloc sever read_buf");
        return NULL;
    }
    
    //接收数据
    //只要能接收到数据 正常使用 一直挂起
    while (count = recv(client_fd,read_buf,1024,0))
    {
        if (count < 0)
        {
            perror("recv");
        }
        
        fputs(read_buf,stdout);
    }
    
    printf("服务端请求关闭\n");
    free(read_buf);
    return NULL;
}

void *write_to_server(void *arg)
{
    //接收控制台输入的信息 写出去
    char *write_buf=NULL;
    int client_fd =*(int*)arg ;
    write_buf = malloc(sizeof(char)*1024);//初始化
    ssize_t count = 0;
    if (!write_buf)
    {
        perror("malloc sever write_buf");
        return NULL;
    }
    while (fgets(write_buf,1024,stdin) != NULL)
    {
        //发送数据
       count = send(client_fd,write_buf,1024,0);
       if (count < 0)
       {
            perror("send");
       }
    }
    printf("接收到控制台的关闭请求 不再写入 关闭连接\n");
    //可以具体到关闭某一端
    shutdown(client_fd,SHUT_WR);
    free(write_buf);
    return NULL;
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sockfd,tmep_result;
    pthread_t pid_read,pid_write;

    //清空
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));

    

    //填写服务端地址
    server_addr.sin_family=AF_INET;
    //填写ip地址 0.0.0.0
    inet_pton(AF_INET,"0.0.0.0",&server_addr.sin_addr);
    //填写端口号
    server_addr.sin_port = htons(6666);

    //客户端网络编程流程
    //1、创建socket
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    handle_error("socket",sockfd);
    //2、绑定地址
    //客户端可以不绑定 系统会自动分配一个空闲的端口号给客户端

    //3、主动连接服务端
    tmep_result = connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));

    printf("链接上服务端 %s %d\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port));

    //创建子线程用于收消息
    pthread_create(&pid_read,NULL,read_from_server,(void*)&sockfd);
    //创建子线程用于发消息
    pthread_create(&pid_write,NULL,write_to_server,(void*)&sockfd);

    //阻塞主线程
    pthread_join(pid_read,NULL);
    pthread_join(pid_write,NULL);

    //释放资源
    printf("释放资源");
    close(sockfd);

    return 0;
}

makefile

cpp 复制代码
mutli_conn_processes_server:mutli_conn_processes_server.c
	-$(CC) -o $@ $^ -lpthread

multi_conn_processes_client:multi_conn_processes_client.c
	-$(CC) -o $@ $^ -lpthread
相关推荐
两个人的幸福10 小时前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo3 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack3 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户3074596982073 天前
PHP 扩展——从入门到理解
php
鹏仔先生4 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下4 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
treesforest4 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
xingpanvip4 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
程序员mine4 天前
HTTPS-TLS加密与证书完全指南(中)
网络协议·https·ssl
之歆4 天前
现代 HTTP 客户端深度解析:Fetch 与 Axios
chrome·网络协议·http