自学内容网 自学内容网

TCP网络socket编程(面向连接)

Tcp面向链接、面向字节流和文件的读写非常类似():客户端创建套接字主动建立连接,服务器监听套接字一直等待连接的到来,监听到一个,就创建一个新的套接字用于IO

服务器:

创建套接字:
在这里插入图片描述
填充网络信息并绑定
在这里插入图片描述
把套接字设置为监听状态——TCP特有
在这里插入图片描述
根据监听套接字,获取客户端的链接:——TCP特有
在这里插入图片描述
服务器收发消息:
在这里插入图片描述

客户端:

启动时:要传入目标服务器的ip port

创建套接字:
在这里插入图片描述
也是不需要手动绑定客户端socket,在于服务器连接完成后自己会绑定网络信息

虽然客户端自己不用绑定网络信息,但是客户端首先要给服务器发消息,所以也是要为目标服务器填一下server的网络类型结构体,供发送使用,
在这里插入图片描述
和目标服务器建立连接:——TCP特有
在这里插入图片描述
向建立连接成功的套接字中读写数据就完成了数据的发送和接收:
在这里插入图片描述

优化:服务器支持多客户端访问——多进程或者多线程
v2:多进程:在获取连接成功后,创建子进程去执行此次链接成功的客户端的求情;
出现的问题:创建子进程文件描述符表会发生拷贝
父进程的文件描述符表就会随着获取连接成功的次数增加,这样就会造成空间的消耗,所以创建完成之后,父子进程应该关闭自己不需要的文件描述符,(父进程关闭新建文件描述符,子进程关闭监听文件描述符)
在这里插入图片描述
但是即使这样还是有个问题:子进程的退出需要父进程等待,如果父进程等待就是阻塞式的等待,那么任然不能实现多客户端连接,
解决方案:子进程再创建一个子进程(孙子进程),然后让子进程退出,孙子进程去完成收发;
在这里插入图片描述
v3:多进程信号版

signal(SIGCHLD,SIG_IGN);//对SIG_IGN信号进行忽略,子进程退出后不用等待自动释放

就不用创建孙子进程,因为父进程不用等待了,就直接用子进程执行收发
在这里插入图片描述
v4:多线程
主线程和新线程不需要关闭所谓的文件描述符,因为他们是共享文件描述符表的如果一个关闭,另外一个也就看不到了
问题:主线程也是会阻塞等待:解决:子线程和主主线程分离

//         pthread_detach(pthread_self());//把自己分离

但是子线程要执行的函数传参的时候如果只传socket的话,因为主线程会一直去监听创建新的socket,所以socket的值是一直变化的不能直接传给子线程执行,要在建立子线程之前先把他保存起来:

//创建一个类用来保存可靠的保存文件描述符,因为如果是创建多线程来收发消息的话,就要把获取到的文件描述符值传过去,但是主线程又会不停地获取,那么如果直接传&sockfd的话,在主线程再次去获取新的是,sockfd这个变量里面保存的值就会被清空(线程调度)
// class ThreadData
// {
//     public:
//     ThreadData(int sock,TcpServer*ptr,sockaddr_in peer):sockfd(sock),svr_ptr(ptr),addr(peer)
//     {}
//     int Sockfd()
//     {
//     return sockfd;
//     }
//     TcpServer*GetServer() {return svr_ptr;};

//     ~ThreadData()
//     {}

//     private:
//     int sockfd;
//     TcpServer* svr_ptr;
//     public:
//     InetAddr addr;

// };
//   static  void *HandlerRequest(void*args)
//     {
//         ThreadData *td=static_cast<ThreadData*>(args);
//         //主线程和新线程不需要关闭所谓的文件描述符,因为他们是共享文件描述符表的如果一个关闭,另外一个也就看不到了
//         pthread_detach(pthread_self());//把自己分离
//         //现在就可以执行收发喽
//             td->GetServer()->Service(td->Sockfd(),td->addr);
//              close(td->Sockfd());
//        delete td;
//         return nullptr;
//     }

// //v4多线程
        // //把这一次的文件描述符保存起来
        // ThreadData *td=new ThreadData(sockfd,this,peer);
        // pthread_t tid;
        // pthread_create(&tid,nullptr,HandlerRequest,td);

总代码链接
在这里插入图片描述
在这里插入图片描述


原文地址:https://blog.csdn.net/qq2127189274/article/details/139358326

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!