`

TcpClient

 
阅读更多
TcpClient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#define ERR_REUSEADDR	-14
#define TCP_SEND_FAIL   -1  //tcp发送失败
#define TCP_BIND_FAIL   -2  //tcp绑定失败
#define TCP_CONN_FAIL   -3  //tcp连接失败
#define TCP_ERROR_ATTR -4 //错误的参数
#define CONNECT_TIME_OUT_MIN 10000 //tcp连接超时最小时间(微秒)
#define CONNECT_TIME_OUT_MAX 250000 //tcp连接超时最大时间(微秒)
#define SYS_FD_BUFF_SZ 128000
#define USE_UNBLOCK 1   //

class TCPClient
{
public:
    TCPClient();

    ~TCPClient();

    //初始
    int init();

    //释放
    void destroy();

    //建立tcp连接
    int conn(const char *ip, unsigned short port,unsigned short localPort=0);

    //发送数据,0:正常,-1:失败,-2:连接失败
    int send(char *msg, int len);

    //接收数据
    int recv(char *msg, int maxlen, int ms);

    //关闭tcp连接
    int close();

    //获取sockfd
    int getSocketFD()const;

    //设置连接超时
    void setConnTimeout(int msecond);

    //获取本机ip和端口,0: 成功, 1: 失败
#ifdef __linux__
    int tcpGetLocalAddr(char *ip, unsigned short *port);
#endif

private:
    //增大缓冲区
    void increaseFdBuff();

private:
    //fd
    int mSockfd;

    //连接ip
    char mIP[16];

    //连接端口
    unsigned short mPort;

    //连接超时时间
    int mConnTimeout;
};




#endif // TCPCLIENT_H




TcpClient.cpp
#include "TcpClient.h"
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#ifndef __linux__
#include <WinSock.h>
#endif

TCPClient::TCPClient()
{
    mSockfd = -1;
    bzero(mIP,sizeof(mIP));
    mPort = 0;
    mConnTimeout = CONNECT_TIME_OUT_MIN;
    init();
}

TCPClient::~TCPClient()
{
    close();
    destroy();
}

/*
    初始化
*/
int TCPClient::init()
{
#ifndef __linux__
    int ret = 0;
    WSADATA wsaData;
    if ((ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
    {
        return -1;
    }
#endif
    return 0;
}

/*
    释放
*/
void TCPClient::destroy()
{
#ifndef __linux__
    WSACleanup();
#endif
}

/*
    建立tcp连接
*/
int TCPClient::conn(const char *ip, unsigned short port, unsigned short localPort)
{
    if(port<=0||strlen(ip)==0){
        return TCP_ERROR_ATTR;
    }
#ifdef __linux__
    strcpy(mIP, ip);
    mPort = port;

    if (mSockfd > 0){
        close();
    }

    if ((mSockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        return TCP_CONN_FAIL;
    }

    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));

    if(localPort>0)
    {
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        addr.sin_port = htons(localPort);
        //绑定客户端的地址信息,使得客户端的端口号固定
        if(bind(mSockfd,(struct sockaddr *)&addr,sizeof(addr))<0){
            return TCP_BIND_FAIL;
        }
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port = htons(port);

#if USE_UNBLOCK
    timeval tm;
    fd_set set;
    unsigned long ul = 1;
    ioctl(mSockfd, FIONBIO, &ul); //设置为非阻塞模式
    int len = sizeof(int);
    bool ret = false;
    int error = -1;
    if( connect(mSockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    {
        tm.tv_sec = 0;
        tm.tv_usec = mConnTimeout;
        FD_ZERO(&set);
        FD_SET(mSockfd, &set);
        if( select(mSockfd+1, NULL, &set, NULL, &tm) > 0)
        {
            getsockopt(mSockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
            if(error == 0){
                ret = true;
            }else{
                ret = false;
            }
        }else
        {
            ret = false;
        }
    }else{
        ret = true;
    }
    ul = 0;
    ioctl(mSockfd, FIONBIO, &ul); //设置为阻塞模式
    if(!ret)
    {
        close();
        return -1;
    }else
    {
        increaseFdBuff();
    }
#else

    if (connect (mSockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
    {
        close();
        return -1;
    }
#endif
    return 0;
#else
    //windows version
    struct sockaddr_in addr;

    if ((m_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        return -1;
    }

    //设置非阻塞
    unsigned long u1 = 1;
    int ret = ioctlsocket(m_sockfd,FIONBIO,(unsigned long*)&u1);
    if(ret==SOCKET_ERROR){
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port = htons(port);

    ret = connect (m_sockfd, (struct sockaddr *) &addr, sizeof(addr));

    struct timeval timeout;
    fd_set r;
    FD_ZERO(&r);
    FD_SET(m_sockfd,&r);
    timeout.tv_sec = 2;
    timeout.tv_usec = 500000;
    ret = select(0,0,&r,0,&timeout);
    if(ret<=0)
    {
        ::closesocket(m_sockfd);
        return 0;
    }

    //设置成非阻塞
    unsigned long ul1 = 0;
    ret = ioctlsocket(m_sockfd,FIONBIO,(unsigned long*)&ul1);
    if(ret==SOCKET_ERROR)
    {
        ::closesocket(m_sockfd);
        return -1;
    }


    return m_sockfd;
#endif
}


/*
    接收数据
*/
int TCPClient::recv(char *msg, int maxlen, int ms)
{
    if (mSockfd < 0)
    {
#ifdef __linux__
        usleep(ms * 1000);
#else
        Sleep(ms);
#endif
        return -99;
    }

    int ret = 0;
    timeval tv;
    if (ms > 0)
    {
        tv.tv_sec = ms / 1000;
        tv.tv_usec = (ms % 1000) * 1000;

        fd_set rset;
        FD_ZERO(&rset);
        FD_SET(mSockfd, &rset);
        ret = select(mSockfd + 1, &rset, NULL, NULL, &tv);
        if (ret == 0)
        {
            return -1;
        }
        else if (ret < 0)
        {
            return ret;
        }
        else
        {
            if(mSockfd<0){
                return -1;
            }
            if (! FD_ISSET(mSockfd, &rset)){
                return -1;
            }
        }
    }

#ifdef __linux__
    ret = read(mSockfd, msg, maxlen);
#else
    ret = recv(m_sockfd, msg, maxlen, 0);
#endif
    if (ret <= 0){
        close();
    }

    return ret;
}

/*
    发送数据,0:正常,-1:失败,-99:连接失败
*/
int TCPClient::send(char *msg, int len)
{
    int r = 0;

    if (mSockfd <= 0){
        if(conn(mIP, mPort) < 0){
            return TCP_CONN_FAIL;
        }
    }

    while (len > 0)
    {
#ifdef __linux__
        r = write(mSockfd, msg, len);
#else
        r = send(m_sockfd, msg, len, 0);
#endif
        if (r <= 0)
        {
            close();
            return TCP_SEND_FAIL;
        }
        msg +=  r;
        len -= r;
    }
    return 0;
}

/*
    关闭tcp连接
*/
int TCPClient::close()
{
    if (mSockfd > 0)
    {
#ifdef __linux__
        ::close(mSockfd);
#else
        closesocket (m_sockfd);
#endif
        mSockfd = -1;
    }
    return 0;
}

/*
    获取sockfd
*/
int TCPClient::getSocketFD()const
{
    return mSockfd;
}

/*
    设置连接超时
*/
void TCPClient::setConnTimeout(int msecond)
{
    if(msecond<CONNECT_TIME_OUT_MIN){
        mConnTimeout = CONNECT_TIME_OUT_MIN;
    }else if(msecond>CONNECT_TIME_OUT_MAX){
        mConnTimeout = CONNECT_TIME_OUT_MAX;
    }else{
        mConnTimeout = msecond;
    }
}

/*
    增大缓冲区
*/
void TCPClient::increaseFdBuff()
{
    int bufSize = SYS_FD_BUFF_SZ;
    setsockopt(mSockfd,SOL_SOCKET,SO_SNDBUF,&bufSize,sizeof(bufSize));
    setsockopt(mSockfd,SOL_SOCKET,SO_RCVBUF,&bufSize,sizeof(bufSize));
}

/*
    获取本机ip和端口,0: 成功, 1: 失败
*/
#ifdef __linux__
int TCPClient::tcpGetLocalAddr(char *ip, unsigned short *port)
{
    struct sockaddr_in addr;
    bzero(&addr,sizeof(addr));
    socklen_t len = sizeof(addr);
    if(! getsockname(mSockfd, (struct sockaddr *) (&addr), &len))
    {
        *port = (unsigned short) ntohs(addr.sin_port);
        if (inet_ntop(AF_INET, &(addr.sin_addr.s_addr), ip, INET_ADDRSTRLEN)){
            return 0;
        }
    }
    return -1;
}
#endif



分享到:
评论

相关推荐

    C# Socket实现TCPClient

    在这个场景中,我们将主要讨论如何使用C#的Socket类来实现TCPClient,一个用于作为TCP客户端的角色进行网络连接的类。 TCP是一种面向连接的、可靠的传输协议,它确保了数据包的顺序传输和错误校验。TCPClient是.NET...

    c#tcpClient发送和接收

    在.NET框架中,C#语言提供了丰富的网络编程接口,其中包括`System.Net.Sockets`命名空间下的`TcpClient`类。这个类允许我们创建TCP/IP客户端,用于与服务器进行可靠的、基于流的数据通信。在这个主题中,我们将深入...

    TcpClient 异步读取数据

    在.NET框架中,`TcpClient`类是用于网络通信的重要组件,主要负责TCP协议的客户端操作。本篇文章将深入探讨如何使用`TcpClient`进行异步读取数据以及如何维护连接状态。 首先,异步读取数据是网络编程中常见且重要...

    Tcpclient连接服务器连接超时设置

    在使用C#的`System.Net.Sockets`命名空间中的`TcpClient`类进行TCP连接时,可能会遇到连接超时的问题。本篇文章将深入探讨如何设置`TcpClient`的连接超时功能。 首先,我们需要了解`TcpClient`类的基本用法。`...

    c# socket 、TCPClient、TCPListener 用法详解.doc

    C# Socket、TCPClient、TCPListener 用法详解 C# 中的 Socket 编程是基于 Windows Sockets (Winsock) 接口的托管实现,提供了一个强大且灵活的网络编程模型。在本文中,我们将详细介绍 C# 中的 Socket 编程,包括 ...

    C#编写的TCPClient

    在.NET框架中,`TCPClient`是用于实现客户端TCP网络通信的基础类,它位于`System.Net.Sockets`命名空间内。TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。`TCPClient...

    C#,winform,Tcp通信源码 使用TcpListener和TcpClient 源码

    在.NET框架中,C#语言提供了丰富的网络编程接口,其中包括TcpListener和TcpClient类,这两个类是用于实现基于TCP协议的客户端与服务器端通信的核心组件。本篇文章将深入探讨这两个类的工作原理、如何使用以及相关的...

    TcpClient局域网传输文件工具

    【TcpClient局域网传输文件工具】是一款个人开发的实用软件,主要应用于局域网内的文件快速分享与传输。此工具基于.NET Framework平台,利用TCP协议实现数据的可靠传输,适用于办公室、家庭网络等局域网环境,方便...

    基于C# 的TcpClient/TcpListener的一对多的网络通信程序源码

    本文将深入探讨基于C#的TcpClient和TcpListener类如何用于构建一对一或多对多的网络通信程序,以及如何在Winform环境中实现这样的系统。 TcpClient和TcpListener是.NET Framework中的两个核心类,分别用于客户端和...

    基于tcplistener和tcpclient的一对多通讯原型

    本知识点主要关注如何使用C#中的`TcpListener`和`TcpClient`类实现一对多的通讯原型,这将帮助初学者理解如何构建简单的网络通信系统。 首先,`TcpListener`是.NET Framework中用于监听TCP连接的类。它的工作原理是...

    Tcpclient循环发送数据实例

    在.NET框架中,`TcpClient`是一个非常重要的网络编程类,用于实现TCP协议的客户端功能。这个实例展示了如何使用`TcpClient`进行循环发送数据,同时处理客户端退出时的服务端响应,确保网络通信的稳定性和可靠性。...

    C#利用TcpClient/TcpListener类结合网络流建立的简单文件传输软件

    在C#编程环境中,开发基于TCP协议的文件传输软件是一项常见的任务,这通常涉及到使用`TcpClient`和`TcpListener`类以及网络流的概念。这两个类是.NET Framework提供的,用于实现客户端和服务器之间的TCP通信。下面...

    IP端口检测工具 TcpClient 优化超时 设备在线检测工具

    本文将深入探讨IP端口检测工具、TcpClient类的优化超时设置以及设备在线检测工具的相关知识点。 首先,我们来理解IP端口检测。IP端口是网络通信中的一个关键概念,它类似于网络上的门牌号,允许不同的服务通过特定...

    PyPI 官网下载 | TCPClient-0.0.20.tar.gz

    《PyPI与TCPClient库详解》 在Python的开发中,PyPI(Python Package Index)是全球最大的Python软件包仓库,它为开发者提供了一个集中发布和下载Python模块的平台。"TCPClient-0.0.20.tar.gz"是PyPI上一个名为...

    TcpListener 和TcpClient使用总结

    ### TcpListener 和 TcpClient 使用总结 #### 一、概述 在C#的.NET框架中,TCP编程是一项重要的技能,尤其适用于构建需要通过网络进行通信的应用程序。本文将深入探讨TcpListener与TcpClient类的使用方法及其背后...

    C#WinForm开发之TCPCLIent通信

    在C# WinForm开发中,TCPClient通信是构建网络应用程序的一种常见方法,它允许客户端与服务器之间进行可靠的、面向连接的数据传输。TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的...

    Delphi 中TcpServer和TcpClient用法

    ### Delphi 中TcpServer和TcpClient用法详解 #### 一、引言 Delphi 是一种功能强大的开发工具,广泛应用于各种应用软件的开发。它不仅支持多种编程语言,还能利用丰富的类库来快速实现复杂的功能。在Delphi中,...

    C# socket学习所得 关于TcpListener与TcpClient

    ### C# Socket 学习心得:关于TcpListener与TcpClient 在.NET框架中,网络通信模块为我们提供了多种方便快捷的接口来实现不同层次的通信需求。其中,`TcpClient`类和`TcpListener`类是两个重要的应用层类,它们为...

    C#TcpClient(客户端)_and_TcpServer(服务端).txt

    TcpClient(客户端) 和 TcpServer(服务端)代码示例 TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求。 可使用 TcpClient 或 Socket 来连接 TcpListener。 可使用 IPEndPoint、本地 IP ...

    使用TcpClient实现telnet功能

    在.NET框架中,`TcpClient`类是用于创建TCP客户端连接的一个强大工具,它允许我们构建基于TCP协议的应用程序,例如模拟telnet功能。Telnet是一种远程登录协议,通过它用户可以在一个计算机上操作另一个远程计算机。...

Global site tag (gtag.js) - Google Analytics