zoukankan      html  css  js  c++  java
  • socket编程(TCP)

    由于服务端和和客户端有的代码是共用的,为了提高编译速度,所以用一个文件socketdll保存共享文件,生成动态链接库,以便调用。

    socketdll文件含有:

    XTcp.h:

    #ifndef  __XTCP__H__
    #define __XTCP__H__
    #ifdef WIN32
    #ifdef SOCKETDLL_EXPORTS
    #define SOCKETDLL_API __declspec(dllexport)
    #else
    #define SOCKETDLL_API __declspec(dllimport)
    #endif
    #else
    #define SOCKETDLL_API
    #endif
    
    class SOCKETDLL_API XTcp
    {
    public:
        XTcp();
        virtual ~XTcp();
        int CreateSocket();
        bool Bind(unsigned short port);
        bool Connect(const char* ip,unsigned short port);
        XTcp Accept();
        int Recv(char *buf,int bufsize);
        int Send(const char* buf,int sendsize);
        void Close();
        int sock = 0;
        unsigned short port = 0;
        char *ip;
    
    };
    #endif 

    XTcp.cpp

    #include "XTcp.h"
    #include<string.h>
    #include<stdio.h>
    #ifdef    WIN32
    #include<windows.h>
    #define socklen_t int
    #else
    #include<unistd.h>
    #include<sys/socket.h>
    #include<sys/types.h>
    #include<arpa/inet.h>
    #define closesocket close
    #endif
    
    XTcp::XTcp()
    {
    #ifdef WIN32
        static int first = true;
        if (first)
        {
            first = false;
            WSADATA ws;
            WSAStartup(MAKEWORD(2,2),&ws);
        }
    #endif 
    
    }
    
    //创建socket
    int XTcp::CreateSocket()
    {
        sock = socket(AF_INET,SOCK_STREAM,0);
        if (sock <= 0)
        {
            printf("创建socket失败!
    ");
            return sock;
        }
        printf("创建socket成功!sock=%d
    ",sock);
        return sock;
    }
    
    bool XTcp::Bind(unsigned short port)
    {
        if (sock <= 0) CreateSocket();
    
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(0);
        addr.sin_port = htons(port);
    
        if (::bind(sock, (sockaddr*)&addr, sizeof(addr)) != 0)
        {
            printf("绑定失败!
    ");
            return false;
        }
        printf("绑定成功! port=%d
    ",port);
        printf("开始监听...
    ");
        listen(sock,20);
        return true;
    }
    
    //accept的行为是被动的
    XTcp XTcp::Accept()
    {
        XTcp xtcp;
    
        sockaddr_in addr;
        socklen_t len = sizeof(addr);
    
        int client = accept(sock, (sockaddr*)&addr, &len);
        if (client <= 0)
        {
            return xtcp;
        }
    
        xtcp.sock = client;
       
        xtcp.ip = inet_ntoa(addr.sin_addr);
        xtcp.port = ntohs(addr.sin_port);
    
        printf("ip:%s %d
    ",xtcp.ip,xtcp.port);
    
        return xtcp;
    }
    
    
    int XTcp::Recv(char *buf, int bufsize)
    {
        return recv(sock,buf,bufsize,0);
    }
    
    int XTcp::Send(const char* buf, int sendsize)
    {
        int x = 0;
        while (x != sendsize)
        {
            int len = send(sock,buf+x,sendsize-x,0);
            x += len;
        }
        return x;
    }
    
    void XTcp::Close()
    {
        if (sock <= 0)
        {
            closesocket(sock);
        }
    }
    
    bool XTcp::Connect(const char* ip, unsigned short port)
    {
        if (sock <= 0) CreateSocket();
        
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip);
    
        if (connect(sock, (sockaddr*)&addr, sizeof(addr)) != 0)
        {
            printf("connect:%s %d,failed:%s
    ",ip,port,strerror(sock));
            return false;
        }
    
        printf("connect:%s %d success!
    ", ip, port);
        return true;
    }
    
    
    
    
    
    
    XTcp::~XTcp()
    {
    }

    makefile:

    libsocketdll.so:XTcp.cpp XTcp.h
    	g++ $+ -o $@ -fpic -shared -std=c++11
    	cp *.so /usr/lib/
    

     makefile结构解释:

    libsocketdll.so    lib动态库的名字.so

    -fpic:该参数表示去共享库寻找时不受地址改变而改变,也就是要用到该共享库,回到固定的地方寻找。

    后面的操作还是找不到以来的库,所以把生成的依赖库复制到系统中去。

    ok。现在共享库完成。


    接下来看服务器端:
    tcpserver文件:

    tcpserver.cpp:

    #include "XTcp.h"
    #include<string.h>
    #include<stdlib.h>
    #include<thread>
    class XTcpThread
    {
    public:
        XTcp client;
        void Main()
        {
            char buf[1024] = {0};
            for (;;)
            {
                int x = client.Recv(buf,sizeof(buf)-1);
                if (x <= 0) break;
                buf[x] = '';
                if (strstr(buf, "quit") != NULL)
                {
                    char re[] = "quit success!
    ";
                    client.Send(re,strlen(re)+1);
                    break;
                }
                int sendlen = client.Send("ok!
    ",4);
                printf("%s
    ",buf);
                break;
            }
            client.Close();
            delete this;    
        }
    };
    int main(int argc,char* argv[])
    {
        unsigned short port = 8080;
        if (argc > 1)
        {
            port = atoi(argv[1]);
        }
        XTcp x;
        x.CreateSocket();
        x.Bind(port);
        
        for (;;)
        {
            XTcp client = x.Accept();
            XTcpThread* a = new XTcpThread();
            a->client = client;
            std::thread th(&XTcpThread::Main,a);
            th.detach();
        }
        x.Close();
    
        while (1);
        return 0;
    }
    makefile文件:

    server:tcpserver.cpp
      g++ $+ -o $@ -I../socketdll  -std=c++11 -lpthread -lsocketdll -L../socketdll 
    

                                           头文件的位置                                              依赖库的名字     依赖库所在位置


    接下来是客户端:

    tcpclient文件:
    tcpclient.cpp:

    #include "XTcp.h"
    
    int main()
    {
        XTcp client;
        client.Connect("192.168.213.133",4000);
         
    
    
        
        return 0;
    }
    makefile文件:
    tcpclient:main.cpp
    	g++ $+ -o $@ -I../socketdll -std=c++11 -lpthread -lsocketdll -L../socketdll 

    目录结构:

    tcpserver文件

    tcpclient文件

    socketdll文件

    最终效果:

    linux开启服务端:

    SecureCRT开启了两个客户端进行连接:



  • 相关阅读:
    3dsmax不同版本 pyside qt UI 设置max窗口为父窗口的方法
    oracle中的数据库和实例
    oracle中的表空间(tablespace)、方案(schema)、段(segment)、区(extent)、块(block)
    什么是WSE
    Server.Transfer,Response.Redirect的区别
    Oracle 中的几个数据类型介绍
    oracle中的连接字符串
    Oracle中的 单引号 和 双引号
    接口是否可以继承接口?抽象类是否可以实现接口?抽象类是否可以继承实体类?
    聚簇索引
  • 原文地址:https://www.cnblogs.com/SunShine-gzw/p/13414726.html
Copyright © 2011-2022 走看看