问个socket的问题。
RyanPoy
2007-06-12
在写socket程序的时候,现在出现了一个问题。具体的是什么原因,没有找到。google上和论坛里都没有找到。请大人们帮忙解决。问题是这样的:一个Server端。一个Client端。Server接收数据时候,因为client端的socket关闭了。(是我手动关闭的,用来模拟数据传输失败的场景),结果Server端的程序都死掉了。实在是找不出原因。本人采用的操作系统:Server端是红帽企业版3.0,client是windows。编程语言:Server端是c++,client是java。现在把代码贴出来。如下。
|
|
RyanPoy
2007-06-12
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__ |
|
RyanPoy
2007-06-12
socket封装的实现文件
#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; } //------------------------------------------------------------------------- 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: // (0)_TCP: connection return createTCP(); case _UDP: // (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; } //------------------------------------------------------------------------- BaseSocket BaseSocket::accept() { struct sockaddr_in clientAddr; // 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)); } //------------------------------------------------------------------------- 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);//??? #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 } |
|
RyanPoy
2007-06-12
main方法
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; } |
|
RyanPoy
2007-06-12
上面是server的测试代码。client的是java写的。就不帖了。但是,当client端关闭的时候,整个应用程序都死掉了。我看了一下server的错误信息,是:socket recv error 104 : Connection reset by peer.但是,一个socket通信失败,不应该把整个程序都down掉啊。实在找不出原因了。请赐教
|
|
RyanPoy
2007-06-13
大侠们都来看看啊。阿!
|
|
qiezi
2007-06-14
客户端和服务器是在内网吗?通常断开服务器会得到通知,这时recv返回是0。但非正常断开则不一定,比如拔网线,这可能要等到TCP超时,这个时间非常长。这样阻塞接收最好是设一下socket超时,通常编写服务器最好是采用事件方式,有数据时处理,而不是这样阻塞线程,当然简单应用是可以的。
|
|
RyanPoy
2007-06-14
这个东西,找到原因.是因为,socket接受或者发送数据失败的时候, 系统给了一个sigpipe信号.导致程序退出.现在这个问题倒是解决了.注册一个信号捕捉函数.然后处理就可以了.
qiezi 写道 客户端和服务器是在内网吗?通常断开服务器会得到通知,这时recv返回是0。但非正常断开则不一定,比如拔网线,这可能要等到TCP超时,这个时间非常长。
是内网.而且,这个不知道为什么常常发生.表现在数据还没有完全接受完毕.然后,就出现recv的返回值为0的情况.实在不知道怎么回事了.没有办法.只能认为这次操作失败了. qiezi 写道 这样阻塞接收最好是设一下socket超时,
我在编写程序的时候,已经设置了超时. qiezi 写道 通常编写服务器最好是采用事件方式,有数据时处理,而不是这样阻塞线程,当然简单应用是可以的。
这个不知道怎么用.能不能举个简单的例子.能有代码最好,而且希望能配上注释. ^-^ |
|
qiezi
2007-06-14
那是broken pipe,是要处理掉的。
事件方式最简单的可以采用select,跨平台,搜索一下就有了。更深入点的,windows上有IOCP,linux下有poll/epoll/aio等。 |
|
RyanPoy
2007-06-14
qiezi 写道 那是broken pipe,是要处理掉的。
事件方式最简单的可以采用select,跨平台,搜索一下就有了。更深入点的,windows上有IOCP,linux下有poll/epoll/aio等。 多谢。不懂再请教。 |