免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 7650 | 回复: 29
打印 上一主题 下一主题

socket问题。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-06-12 17:36 |只看该作者 |倒序浏览
在写socket程序的时候,现在出现了一个问题。具体的是什么原因,没有找到。google上和论坛里都没有找到。请大人们帮忙解决。问题是这样的:一个Server端。一个Client端。Server接收数据时候,因为client端的socket关闭了。(是我手动关闭的,用来模拟数据传输失败的场景),结果Server端的程序都死掉了。实在是找不出原因。本人采用的操作系统:Server端是红帽企业版3.0,client是windows。编程语言:Server端是c++,client是java。现在把代码贴出来。如下。
对socket的封装。头文件:
#ifndef __BASE_SOCKET__
#define __BASE_SOCKET__

#define _LINUX__

#ifdef _WIN32__
    #pragma comment(lib, "ws2_32.lib")
#endif
    
#ifdef _LINUX__
    #include <unistd.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #ifndef SOCKET
        #define SOCKET int
    #endif
#endif
    
#define _TCP 0
#define _UDP 1

#define SOCKET_EXCEPTION -1

class BaseSocket
{
protected:
    struct sockaddr_in addr;   
    SOCKET sock;

public:
    BaseSocket();
    BaseSocket(SOCKET sock);
    BaseSocket(const BaseSocket& bsocket);
    ~BaseSocket();

    bool operator == (const BaseSocket& s)
    {
        return sock == s.sock;
    };

    unsigned short getPort() const;
    char* getIP() const;

    static bool init();
    static bool destroy();

    bool create(int type = _TCP);
    bool isValid();
    bool close();

    bool bind(unsigned short port);
    bool listen(int num = 5);
    BaseSocket accept();
    bool connect(const char* ip, unsigned short port);

    bool recvChar(char* v);
    bool recvShort(short* v);
    bool recvInt(int* v);
    bool recvLong(long* v);
    bool recvI64(I64* v);
    bool recvStr(char* str, int len);

    bool send(char data);
    bool send(short data);
    bool send(int data);
    bool send(long data);
    bool send(I64 data);
    bool send(U_I64 data);
    bool send(char* str, int len);
    bool setTimeOut(int millSec);

protected:
    bool createTCP();
    bool createUDP();
    bool realCreate(int af = AF_INET, int type = SOCK_STREAM, int protocol = IPPROTO_TCP);
};

#endif //~__BASE_SOCKET__

论坛徽章:
0
2 [报告]
发表于 2007-06-12 17:39 |只看该作者
实现文件如下:
#include "BaseSocket.h"
#include <cstdio>

BaseSocket::BaseSocket(): sock(-1){}

BaseSocket::BaseSocket(SOCKET sock): sock(sock){}

BaseSocket::BaseSocket(const BaseSocket& bsocket): sock(bsocket.sock), addr(bsocket.addr){}

BaseSocket::~BaseSocket(){}

bool BaseSocket::recvChar(char* v)
{
    return recvStr(v, sizeof(char));
}

//-------------------------------------------------------------------------


bool BaseSocket::recvShort(short* v)
{
    return recvStr((char*) v, sizeof(short));
}

//-------------------------------------------------------------------------


bool BaseSocket::recvInt(int* v)
{
    return recvStr((char*) v, sizeof(int));
}

//-------------------------------------------------------------------------


bool BaseSocket::recvLong(long* v)
{
    return recvStr((char*) v, sizeof(long));
}

//-------------------------------------------------------------------------


bool BaseSocket::recvI64(I64* v)
{
    return recvStr((char*) v, sizeof(v));
}

//-------------------------------------------------------------------------

bool BaseSocket::recvStr(char* str, int len)
{
    if (NULL == str || 0 > len)
        return false;

    if (len == 0)
        return true;

    int recvLen = ::recv(sock, str, len, 0);
    if (recvLen <= 0)
    {
#ifdef _WIN32__
            printf("socket recv error? %d\n", GetLastError());
#endif
#ifdef _LINUX__
            printf("socket recv error? %d : %s \n", errno, strerror(errno));
#endif
        return false;
    }
    
    while (recvLen < len)
    {
        int relt = ::recv(sock, str + recvLen, len - recvLen, 0);

        if (relt <= 0)
        {
#ifdef _WIN32__
            printf("socket recv error? %d\n", GetLastError());
#endif
#ifdef _LINUX__
            printf("socket recv error? %d : %s \n", errno, strerror(errno));
#endif
            return false;
        }

        recvLen += relt;
    }

    return true;
}

论坛徽章:
0
3 [报告]
发表于 2007-06-12 17:41 |只看该作者
接着来
bool BaseSocket::send(char data)
{
    return send(&data, sizeof(data));
}

//-------------------------------------------------------------------------


bool BaseSocket::send(short data)
{
    return send((char*)& data, sizeof(data));
}

//-------------------------------------------------------------------------


bool BaseSocket::send(int data)
{
    return send((char*)& data, sizeof(data));
}

//-------------------------------------------------------------------------


bool BaseSocket::send(long data)
{
    return send((char*)& data, sizeof(data));
}

//-------------------------------------------------------------------------


bool BaseSocket::send(I64 data)
{
    return send((char*)& data, sizeof(data));
}

//-------------------------------------------------------------------------


bool BaseSocket::send(U_I64 data)
{
    return send((char*)& data, sizeof(data));
}

//-------------------------------------------------------------------------


bool BaseSocket::send(char* str, int len)
{
    int sendLen = ::send(sock, str, len, 0);
    if (sendLen < 0)
    {
#ifdef _WIN32__
        printf("socket send error: %d\n", GetLastError());
#endif
#ifdef _LINUX__
        printf("socket send error: %d, %s\n", errno, strerror(errno));
#endif
        return false;
    }
    while(sendLen < len)
    {
        int relt = ::send(sock, str + sendLen, len - sendLen, 0);
        if (relt < 0)
        {
#ifdef _WIN32__
            printf("socket send error: %d\n", GetLastError());
#endif
#ifdef _LINUX__
            printf("socket send error: %d, %s\n", errno, strerror(errno));
#endif
            return false;
        }
        sendLen += relt;
    }

    return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool BaseSocket::create(int type)
{
    switch (type)
    {
        case _TCP:    [color=#FF9900>// (0)_TCP: connection

            return createTCP();
        case _UDP:  [color=#FF9900>// (1)_UDP: connection

            return createUDP();
        default:
            return false;
    }
}

//-------------------------------------------------------------------------


bool BaseSocket::createTCP()
{
    return realCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}

//-------------------------------------------------------------------------


bool BaseSocket::createUDP()
{
    return realCreate(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}

//-------------------------------------------------------------------------


bool BaseSocket::realCreate(int af, int type, int protocol)
{
    sock = socket(af, type, protocol);
    if (!isValid())
    {
#ifdef _WIN32__
        printf("Create Connect(protocol NO.%d) Error ! : %d\n", protocol, GetLastError());
#endif
#ifdef _LINUX__
        printf("Create Connect(protocol NO.%d) Error ! : %d, %s\n", protocol, errno, strerror(errno));
#endif
        return false;
    }
    return true;
}

论坛徽章:
0
4 [报告]
发表于 2007-06-12 17:43 |只看该作者
再接着来:
BaseSocket BaseSocket::accept()
{
    struct sockaddr_in clientAddr;
    [color=#FF9900>//    memset(&clientAddr, 0x00, sizeof(clientAddr));

#ifdef _WIN32__
    int len = sizeof(sockaddr_in);
#endif
#ifdef _LINUX__
    socklen_t len = sizeof(sockaddr_in);
#endif
    SOCKET sClient = ::accept(sock, (struct sockaddr*)& clientAddr, &len);
    BaseSocket s(sClient);
    s.addr = clientAddr;
    if (!isValid())
    {
#ifdef _WIN32__
            printf("Accept Error ! : %d\n", GetLastError());
#endif
#ifdef _LINUX__
            printf("Accept Error ! : %d, %s\n", errno, strerror(errno));
#endif
    }
    else
    {
            printf("accept client connection : %s -- %d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
    }
    return s;
}

//-------------------------------------------------------------------------


bool BaseSocket::connect(const char* ip, unsigned short port)
{
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    serverAddr.sin_addr.s_addr = inet_addr(ip);
    
    if (-1 == ::connect(sock, (struct sockaddr*)& serverAddr, sizeof(struct sockaddr)))
    {
#ifdef _WIN32__
        printf("Socket Connect Error: %d\n", GetLastError());
#endif
#ifdef _LINUX__
        printf("Socket Connect Error: %d, %S\n", errno, strerror(errno));
#endif
        return false;
    }
    printf("socket %s:%d connect.\n", getIP(), getPort());
    return true;
}

//-------------------------------------------------------------------------


bool BaseSocket::close()
{
    printf("socket %s:%d close.\n", getIP(), getPort());
#ifdef _WIN32__
    if (-1 == ::closesocket(sock))
    {
        printf("socket close error!\n", GetLastError());
        return false;
    }
#endif
#ifdef _LINUX__
    if (-1 == ::close(sock))
    {
        printf("socket close error! %d, %s\n", errno, strerror(errno));
        return false;
    }
#endif
    return true;
}

//-------------------------------------------------------------------------


bool BaseSocket::bind(unsigned short port)
{
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(&addr.sin_zero, 0x00, sizeof(addr.sin_zero));
    
    if (-1 == ::bind(sock, (struct sockaddr*)& addr, sizeof(struct sockaddr)))
    {
#ifdef _WIN32__
        printf("socket bind error! %d\n", GetLastError());
#endif
#ifdef _LINUX__
        printf("socket bind error! %d: %s\n", errno, strerror(errno));
#endif
        return false;
    }
    return true;
}

//-------------------------------------------------------------------------


bool BaseSocket::listen(int num)
{
    if (-1 == ::listen(sock, num))
    {
#ifdef _WIN32__
        printf("listen error! %d\n", GetLastError());
#endif
#ifdef _LINUX__
        printf("listen error! %d: %s", errno, strerror(errno));
#endif

        return false;
    }
    return true;
}

//-------------------------------------------------------------------------


bool BaseSocket::isValid()
{
    return -1 != sock;
}

//-------------------------------------------------------------------------


unsigned short BaseSocket::getPort() const
{
    return (unsigned short) (::ntohs(addr.sin_port));
}

论坛徽章:
0
5 [报告]
发表于 2007-06-12 17:44 |只看该作者
再接着来:
char* BaseSocket::getIP()const
{
    char* p = ::inet_ntoa(addr.sin_addr);
    if (NULL == p)
    {
#ifdef _WIN32__
        printf("Socket Get IP Error: %d\n", GetLastError());
#endif
#ifdef _LINUX__
        printf("Socket Get IP Error: %d, %s\n", errno, strerror(errno));
#endif
    }
    return p;
}

//-------------------------------------------------------------------------


bool BaseSocket::setTimeOut(int milliSec)
{
    if (!isValid())
        return false;
    
#ifdef _WIN32__    
    int time = milliSec;
#endif
#ifdef _LINUX__
    
    struct timeval time;
    time.tv_sec = (milliSec / 1000);[color=#FF9900>//???

#endif
    if (-1 == setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)& time, sizeof(time)))
    {
#ifdef _WIN32__
        printf("Socket Set Timeout Error: %d\n", GetLastError());
#endif

#ifdef _LINUX__
        printf("Socket Set Timeout Error: %d, %s\n", errno, strerror(errno));
#endif
        return false;
    }
    
        if (-1 == setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)& time, sizeof(time)))
    {
#ifdef _WIN32__
        printf("Socket Set Timeout Error: %d\n", GetLastError());
#endif

#ifdef _LINUX__
        printf("Socket Set Timeout Error: %d, %s\n", errno, strerror(errno));
#endif
        return false;
    }
    return true;
}

//-------------------------------------------------------------------------


bool BaseSocket::init()
{
#ifdef _WIN32__
    WSAData wsaData;
    if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
    {
        printf("WSA Startup Error : %d \n", GetLastError());
        return false;
    }
    return true;
#else
    return true;
#endif  
}

//-------------------------------------------------------------------------


bool BaseSocket::destroy()
{
#ifdef _WIN32__
    if (0 != WSACleanup())
    {
        printf("WSA Startup Error : %d \n", GetLastError());
        return false;
    }
    return true;
#else
    return true;
#endif  
    
}

论坛徽章:
0
6 [报告]
发表于 2007-06-12 17:47 |只看该作者
#include "BaseSocket.h"

int main(int argc, char* argv[])
{
    BaseSocket qsSocket;
    
    if (!qsSocket.create(_TCP))
        return -1;
    if (!qsSocket.bind((unsigned short) 8888))
        return -1;
    if (!qsSocket.listen(5))
        return -1;
    
    char* str= "Logger.default.grade=INFO;???????";
    int len = (int) strlen(str);
    BaseSocket csock = qsSocket.accept();
    int v;
    while(true)
    {
        csock.send(len);
        csock.send(str, len);
        csock.recvInt(&v);
        printf("v = %d\n", v);
    }
    return 0;
}

论坛徽章:
0
7 [报告]
发表于 2007-06-12 17:53 |只看该作者
上面的
char* str= "Logger.default.grade=INFO;???????"

中的???????是中文。应该是:“中国人名共和国”,不知道为什么论坛中的代码样式中变成了"??????"。这个不重要。上面是所有的代码。client的是java写的。就不帖了。反正java这东西没有什么技术含量。java大人千万别鄙视我。但是,当client端关闭的时候,整个应用程序都死掉了。我看了一下server的错误信息,是:socket recv error 104 : Connection reset by peer.但是,一个socket通信失败,不应该把整个程序都down掉啊。实在找不出原因了。请大人们赐教啊。

论坛徽章:
0
8 [报告]
发表于 2007-06-12 22:38 |只看该作者
只accept了一次

论坛徽章:
0
9 [报告]
发表于 2007-06-13 09:15 |只看该作者
不用全贴吧,看得累死了。。。。。。

论坛徽章:
0
10 [报告]
发表于 2007-06-13 09:17 |只看该作者
你打log出来看看,到底server是死在那一步的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP