socket C/C++编程(9)windows server端面向对象化处理

来源:互联网 发布:linux调用shell脚本 编辑:程序博客网 时间:2024/05/17 04:15

1. 面向过程的源代码如下,

#include <stdio.h>#include <string.h>#include <thread>#ifdef WIN32    #include <windows.h>    #define socklen_t int#else    #include <sys/types.h>    #include <sys/socket.h>    #include <unistd.h>    #include <stdlib.h>    #include <arpa/inet.h>    #define closesocket close    //#include <thread>#endifusing namespace std;class TcpThread{ // 多线程类public:        void Main(){ // 每一个线程的入口函数            char buf[1024] = {0};            for(;;){                int lenRecv = recv(client,buf, sizeof(buf)-1,0); // server读取client端键入的数据(第二类socket的句柄,存储数据的地方,flag)                if(lenRecv <= 0) break;                buf[lenRecv] = '\0'; // 客户端键入数据的末尾两位赋值‘、0’                if(strstr(buf,"quit")!= NULL){                    break; // 字符串匹配函数,匹配到用户发送了"quit"                }                printf("Recvd data: %s \n Len: %d \n", buf, lenRecv); // 服务器显示客户端键入的字符串长度            }            #ifdef WIN32 // 读取数据的第二类socket创建后要记得关闭                closesocket(client);            #else                close(client);                   #endif            delete this; // 调用完后,自己清理调第二类socket的对象        }        int client;// 每一个客户端的第二类socket};int main(int argc, char *argv[]){    // 初始化”ws2_32.lib”    #ifdef WIN32        WSADATA ws;        WSAStartup(MAKEWORD(2,2), &ws);    #endif    // 创建第一类socket    int sock = socket(AF_INET,SOCK_STREAM,0);    if(sock == -1){        printf("create sock error!\n");        return -1;    }    // TCP Server指定端口并设置服务端端口的属性,返回(sockaddr*)&saddr    unsigned short port = 8080; // 默认端口号    if(argc > 1){        port = atoi(argv[1]);    }    sockaddr_in saddr; // 声明端口    saddr.sin_family = AF_INET; // TCPIP协议    saddr.sin_port = htons(port); // 绑定端口号, htons()之host-to-network    saddr.sin_addr.s_addr = 0; //或htonl(0) 服务器接受的IP地址 0表示接受任意内外网IP    // 绑定端口到指定的socket,输入(sockaddr*)&saddr    if(::bind(sock, (sockaddr*)&saddr, sizeof(saddr))!=0){        printf("OS bind socks to this port %d failed\n", port);        return -2;    }    printf("OS bind this port %d to sockets successfully!\n", port);    listen(sock, 10); // 允许用户连接函数(客户socket(一个客户一个socket),最大请求数队列的长度,)    for(;;){ // 支持多个客户端第二类socket        sockaddr_in caddr; // 结构体:存储客户端的相关信息:端口号和IP地址s        socklen_t len = sizeof(caddr);         int client = accept(sock,(sockaddr*)&caddr,&len); // 第二类socket: 创建一个socket专门读取缓冲区clients(这里缓冲区大小如上行listen代码所示为10)        if(client<=0)break;        printf("accept client %d", client);        char *ip = inet_ntoa(caddr.sin_addr); // 客户端IP地址转字符串        unsigned short cport = ntohs(caddr.sin_port);// 客户端端口号(网络字节序转本地字节序)        printf("client ip: %s, port is %d\n", ip, cport); // 打印客户端连接信息        TcpThread *th = new TcpThread(); // 创建第二类socket对象        th->client = client; // 传递client到TcpThread对象        thread sth(&TcpThread::Main,th); // 启动线程的入口函数main(),参数为thread,函数库为thread sth()        sth.detach();    }    closesocket(sock); // 端口的第一类socket,不再交互后也要记得关闭,先二后一时堆栈思想        getchar();    return 0;}

2. 面向对象化之XTcp.h

#pragma once#include <string>class XTcp{public:    int sock;    unsigned short port;    std::string ip;    int CreateSocket();    bool Bind(unsigned short port);    XTcp Accept();    void Close();    int Recv(char *buf, int bufsize);    int Send(const char *buf, int sendsize);    XTcp(void);    virtual ~XTcp(void);};

3. 面向对象化之XTcp.cpp

#include "XTcp.h"#include <stdio.h>#include <string.h>#include <thread>#ifdef WIN32    #include <windows.h>    #define socklen_t int#else    #include <sys/types.h>    #include <sys/socket.h>    #include <unistd.h>    #include <stdlib.h>    #include <arpa/inet.h>    #define closesocket close    //#include <thread>#endifusing namespace std;// 创建构造函数XTcp::XTcp(void){    // 初始化”ws2_32.lib”->初始化一次    #ifdef WIN32    static bool first = true;    if(first){        first = false;        WSADATA ws;        WSAStartup(MAKEWORD(2,2), &ws);    }    #endif}XTcp::~XTcp(void){}// 创建第一类sockint XTcp::CreateSocket(){    // 创建第一类socket    sock = socket(AF_INET,SOCK_STREAM,0);    if(sock <= 0){        printf("create sock error!\n");    }    return sock;}// 绑定端口和listenbool XTcp::Bind(unsigned short port){    if(sock<=0)        CreateSocket();    sockaddr_in saddr; // 声明端口    saddr.sin_family = AF_INET; // TCPIP协议    saddr.sin_port = htons(port); // 绑定端口号, htons()之host-to-network    saddr.sin_addr.s_addr = 0; //或htonl(0) 服务器接受的IP地址 0表示接受任意内外网IP    // 绑定端口到指定的第一类socket,输入(sockaddr*)&saddr    if(::bind(sock, (sockaddr*)&saddr, sizeof(saddr))!=0){        printf("OS bind socks to this port %d failed\n", port);        return false;    }    printf("OS bind this port %d to sockets successfully!\n", port);    listen(sock, 10); // 允许用户连接函数(客户socket(一个客户一个socket),最大请求数队列的长度,)    return true;}//通过tcp socket判断第二类socket是否成功XTcp XTcp::Accept(){    XTcp tcp;    // 支持多个客户端第二类socket    sockaddr_in caddr; // 结构体:存储客户端的相关信息:端口号和IP地址s    socklen_t len = sizeof(caddr);     int client = accept(sock,(sockaddr*)&caddr,&len); // 第二类socket: 创建一个socket专门读取缓冲区clients(这里缓冲区大小如上行listen代码所示为10)    if(client <= 0) return tcp;    printf("accept client %d", client);    tcp.ip = inet_ntoa(caddr.sin_addr); // 客户端IP地址转字符串    tcp.port = ntohs(caddr.sin_port);// 客户端端口号(网络字节序转本地字节序)    tcp.sock = client;    printf("client ip: %s, port is %d\n", tcp.ip.c_str(), tcp.port); // 打印客户端连接信息    return tcp;}void XTcp::Close(){    if(sock <= 0) return; // sock发生错误    closesocket(sock);}int XTcp::Recv(char *buf, int bufsize){    return recv(sock, buf, bufsize, 0);}// 一定要发送完毕int XTcp::Send(const char *buf, int size){    int s = 0;    while(s!=size){        int len = send(sock, buf+s, size-s,0);         if(len <= 0) break; // 发完退出        s += len;    }    return s;}

4. 面向对象测试之入口函数 Test.cpp

#include <stdlib.h>#include "XTcp.h"#include <thread>class TcpThread{ // 多线程类public:        void Main(){ // 每一个线程的入口函数            char buf[1024] = {0};            for(;;){                int lenRecv = client.Recv(buf, sizeof(buf)-1); // server读取client端键入的数据(第二类socket的句柄,存储数据的地方,flag)                if(lenRecv <= 0) break;                buf[lenRecv] = '\0'; // 客户端键入数据的末尾两位赋值‘、0’                if(strstr(buf,"quit")!= NULL){                    char re[] = "quit success\n";                    client.Send(re, strlen(re)+1);                    break; // 字符串匹配函数,匹配到用户发送了"quit"                }                int sendlen = client.Send("ok\n",4);                printf("Recvd data: %s \n Len: %d \n", buf, lenRecv); // 服务器显示客户端键入的字符串长度            }            client.Close();            delete this; // 调用完后,自己清理调第二类socket的对象        }        XTcp client;// 每一个客户端的第二类socket};int main(int argc, char *argv[]){    // TCP Server指定端口并设置服务端端口的属性,返回(sockaddr*)&saddr        unsigned short port = 9003; // 默认端口号    if(argc > 1){        port = atoi(argv[1]);    }    XTcp server;     //server.CreateSocket();    server.Bind(port);    for(;;){         XTcp client = server.Accept(); // 阻塞函数        TcpThread *th = new TcpThread(); // 创建第二类socket对象        th->client = client; // 传递client到TcpThread对象        std::thread sth(&TcpThread::Main,th); // 启动线程的入口函数main(),参数为thread,函数库为thread sth()        sth.detach();    }    server.Close();    getchar();    return 0;}

客户端并行连接,

这里写图片描述

这里写图片描述

服务端创建sockets,接收队列中的clients,

这里写图片描述

阅读全文
0 0
原创粉丝点击