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
相关推荐
m0_738120721 小时前
渗透测试基础——黑盒测试下的Web漏洞挖掘与利用解析(一)
服务器·前端·网络·安全·php
林熙蕾LXL3 小时前
传输层-UDP介绍
网络·网络协议·udp
catchadmin5 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.3.1 发布 后台打包直降 5s 内
开发语言·php
Leweslyh5 小时前
基于 Confucius 架构的无人集群网络控制原语解析
开发语言·网络·php
Amnesia0_06 小时前
网络层IP
网络·网络协议·tcp/ip
MR.欻6 小时前
ZLMediaKit 源码分析(七):HTTP-FLV 低延迟直播流分析
网络·网络协议·http
北京耐用通信6 小时前
耐达讯自动化PROFIBUS光纤模块:工业通信的“光电翻译官”
人工智能·科技·网络协议·自动化·信息与通信
Zzzzmo_6 小时前
【网络原理】TCP/IP协议01
网络·tcp/ip
ylscode6 小时前
黑客利用 GHOSTYNETWORKS 和 OMEGATECH 托管 JS 恶意软件基础设施
开发语言·安全·php·安全威胁分析