100分求助,SOCKET重新连接的问题

kapil 2012-06-13 09:52:44
下面的代码是连接SOCKET服务器的代码,如何判断SOCKET是否断开?如果断开后自动重连的代码改如何写呢?

----------------------
string socket_ip = "127.0.0.1";

int socket_port = 19001;

if (err)
{
printf("客户端的嵌套字打开失败!\n");
return 0;//结束
}

SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN clientsock_in;
clientsock_in.sin_addr.S_un.S_addr=inet_addr(socket_ip.c_str());
clientsock_in.sin_family=AF_INET;
clientsock_in.sin_port=htons(socket_port);
//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数
//listen(clientSocket,5);
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接

------------------

多谢?
...全文
291 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
cobra_chen 2012-06-13
  • 打赏
  • 举报
回复
服务端无法修改么?
如果是这样,我只能提供一个思路。
在另外的线程或者进程去检查这个socket是否可写。
可以参考select
或者还有其他的检测手段。
-
最好的办法是服务端也做修改。
客户端长时间的阻塞也不是很好。
虽然阻塞模式会让编码变的简单,但是扩展性会差很多。
如果本来就要实现很简单的功能,阻塞模式也是相当好的。
关键看需要用来解决什么问题。

[Quote=引用 15 楼 的回复:]

引用 14 楼 的回复:

如果处理数据会消耗时间很长(5min以上我觉得就比较长了,这个时间看需要更改)。
那么就可以考虑使用多线程,或者多进程,用另外的进程或线程处理数据。
如果再处理数据中,那么程序就无法保证一定连接。
或者另起线程或进程保证连接。
-
重连接的话最简单的方法:关闭现有的socket。重新建立socket。
引用 13 楼 的回复:

引用 10 楼……
[/Quote]
kapil 2012-06-13
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]

如果处理数据会消耗时间很长(5min以上我觉得就比较长了,这个时间看需要更改)。
那么就可以考虑使用多线程,或者多进程,用另外的进程或线程处理数据。
如果再处理数据中,那么程序就无法保证一定连接。
或者另起线程或进程保证连接。
-
重连接的话最简单的方法:关闭现有的socket。重新建立socket。
引用 13 楼 的回复:

引用 10 楼 的回复:

引用 8 楼 ……
[/Quote]

请问在while中如何判断SOCKET是否还连接着呢?

我这个是SOCKET客户端,服务器端不给客户端发送任何的数据。
cobra_chen 2012-06-13
  • 打赏
  • 举报
回复
如果处理数据会消耗时间很长(5min以上我觉得就比较长了,这个时间看需要更改)。
那么就可以考虑使用多线程,或者多进程,用另外的进程或线程处理数据。
如果再处理数据中,那么程序就无法保证一定连接。
或者另起线程或进程保证连接。
-
重连接的话最简单的方法:关闭现有的socket。重新建立socket。
[Quote=引用 13 楼 的回复:]

引用 10 楼 的回复:

引用 8 楼 的回复:

引用 7 楼 的回复:

不是啊,客户端不需要bind,直接connect就行了。


是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?


任何SOCKET的操作出现不可挽回(FATAL)的就重连,比如r……
[/Quote]
kapil 2012-06-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

引用 8 楼 的回复:

引用 7 楼 的回复:

不是啊,客户端不需要bind,直接connect就行了。


是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?


任何SOCKET的操作出现不可挽回(FATAL)的就重连,比如recv,send时候返回错误,并且……
[/Quote]

可能是我没说明白,我把我的代码大概秒数一下:

string socket_ip = "127.0.0.1";

int socket_port = 19001;

if (err)
{
printf("客户端的嵌套字打开失败!\n");
return 0;//结束
}

SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN clientsock_in;
clientsock_in.sin_addr.S_un.S_addr=inet_addr(socket_ip.c_str());
clientsock_in.sin_family=AF_INET;
clientsock_in.sin_port=htons(socket_port);
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接

while(true)
{
// 这里会循环处理很多数据,时间很长,需要一整天
}

// 最后关闭连接
KSFTHQPUB_Stop();

closesocket(clientSocket);
WSACleanup();

我现在遇到的问题是,在while循环中如何判断socket是否连接?如果发现socket已经断开再自动重连,重连的代码该怎么写呢?
cobra_chen 2012-06-13
  • 打赏
  • 举报
回复
确认是否连接,可以发送心跳包。

[Quote=引用 8 楼 的回复:]

引用 7 楼 的回复:

不是啊,客户端不需要bind,直接connect就行了。


是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?
[/Quote]
cobra_chen 2012-06-13
  • 打赏
  • 举报
回复
并且errno不可容忍此话怎讲?
[Quote=引用 10 楼 的回复:]

引用 8 楼 的回复:

引用 7 楼 的回复:

不是啊,客户端不需要bind,直接connect就行了。


是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?


任何SOCKET的操作出现不可挽回(FATAL)的就重连,比如recv,send时候返回错误,并且……
[/Quote]
qq120848369 2012-06-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

引用 7 楼 的回复:

不是啊,客户端不需要bind,直接connect就行了。


是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?
[/Quote]

任何SOCKET的操作出现不可挽回(FATAL)的就重连,比如recv,send时候返回错误,并且errno不可容忍。
cobra_chen 2012-06-13
  • 打赏
  • 举报
回复
用send发送心跳包。

[Quote=引用 8 楼 的回复:]

引用 7 楼 的回复:

不是啊,客户端不需要bind,直接connect就行了。


是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?
[/Quote]
kapil 2012-06-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

不是啊,客户端不需要bind,直接connect就行了。
[/Quote]

是这样的,上面一段代码是我连接服务器的逻辑,在连接之后我会进行一些操作,如果在操作的时候如何判断socket是否还在连接状态?如果发现断掉了,就重新连接呢?
qq120848369 2012-06-13
  • 打赏
  • 举报
回复
不是啊,客户端不需要bind,直接connect就行了。
艳琦罗生 2012-06-13
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

引用 1 楼 的回复:

//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数

你别口口声声喊着第三个参数,结果给一个错的第三个参数,你运气好IPV4的addr和SOCKADDR长度一样,碰到IPV6你还传这个SOCKADDR,你就等死吧。

bind(clientSoc……
[/Quote]
socket 不会判断断开重连 自能自己 发现断开 重新做连接
kapil 2012-06-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数

你别口口声声喊着第三个参数,结果给一个错的第三个参数,你运气好IPV4的addr和SOCKADDR长度一样,碰到IPV6你还传这个SOCKADDR,你就等死吧。

bind(clientSocket,(SOCKADDR*)&……
[/Quote]

十分感谢回复!

上面这个代码是从网上找到的,我本人对C++还是小白。

如果加上了这一行,是不是如果断开了,程序会自动连接?

bind(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR_IN));
xiao0915 2012-06-13
  • 打赏
  • 举报
回复
WSAGetLastError()
艳琦罗生 2012-06-13
  • 打赏
  • 举报
回复
CMySock::BindSock()
{
sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(4444);

int opt = 1;
int ret = setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&opt, sizeof(opt));
if (ret == SOCKET_ERROR)
return -1;

ret=bind(m_sock,(sockaddr *)&servaddr,sizeof(servaddr));
if (ret == SOCKET_ERROR)
int err = WSAGetLastError();

return 0;
}
cobra_chen 2012-06-13
  • 打赏
  • 举报
回复
楼上说的对。
-
如果连接断开,那么在recv或者send的时候就会失败,window的话可以调用WSAGetLastError(),查看错误代码。linux用errno。
qq120848369 2012-06-13
  • 打赏
  • 举报
回复
//bind(clientSocket,(SOCKADDR*)&clientsock_in,strlen(SOCKADDR));//注意第三个参数

你别口口声声喊着第三个参数,结果给一个错的第三个参数,你运气好IPV4的addr和SOCKADDR长度一样,碰到IPV6你还传这个SOCKADDR,你就等死吧。

bind(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR_IN));
connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR_IN));//开始连接
KING_314 2012-06-13
  • 打赏
  • 举报
回复

BOOL CTcpip::Tcp_ClientOpenInet(unsigned long ip, unsigned short port)
{
struct sockaddr_in server;
int rval;
unsigned long argp = 1;

struct timeval tv;
char errmsg[255];
fd_set fd;
fd_set readfd;
time_t t1, t2 ;
unsigned char * p;

memcpy(&(server.sin_addr), &ip, sizeof(server.sin_addr));
server.sin_port = htons(port);
server.sin_family = AF_INET;

clisock = socket(AF_INET, SOCK_STREAM, 0);
if (clisock < 0)
{
/* sockid == -1 */
sprintf(errmsg, "Client: socket() create. with error %d",
WSAGetLastError());
DebugLog(errmsg);
return FALSE;
}

ioctlsocket(clisock, FIONBIO, &argp);
FD_ZERO(&fd);
FD_ZERO(&readfd);

time(&t1) ;
t2 = t1 + 5 ;

while (WaitForSingleObject(gReadDataEvent, 30) != WAIT_OBJECT_0)
{
rval = connect(clisock, (struct sockaddr *) &server, sizeof(server)) ;
if (rval != 0)
{
FD_SET(clisock, &fd);
tv.tv_sec = 0; //gwcfg.timeout;
tv.tv_usec =5000L; //500000L;

FD_SET(clisock, &readfd);
tv.tv_sec = 0;
tv.tv_usec = 5000L;
if ((rval = select(0, &readfd, &fd, NULL, &tv)) <= 0)
{
if (rval == SOCKET_ERROR)
{
int Error = WSAGetLastError();
switch(Error)
{
case WSANOTINITIALISED:
break;
case WSAEFAULT: //currently ignore this condition
TRACE(_T("WARNING: MAX. Message Size exceeded\n"));
break;
case WSAENETDOWN:
break;
default:
{
TCHAR buffer[512];
wsprintf(buffer, _T("SendTo() returned %d"), Error);
}
break;
}
}
time(&t1) ;
if (t1 > t2)
{
/* time out */
closesocket(clisock);
p = (unsigned char *) &ip;
return FALSE ;
}
}
else
{
argp = 0; // none block
if (!AsyncMode)
ioctlsocket(clisock, FIONBIO, &argp);
return TRUE;
}
}
else
{
argp = 0; // none block
if (!AsyncMode)
ioctlsocket(clisock, FIONBIO, &argp);
return TRUE;
}
}
return FALSE;
#endif
}

KING_314 2012-06-13
  • 打赏
  • 举报
回复

BOOL CTcpip::Tcp_ClientOpenInet(unsigned long ip, unsigned short port)
{
struct sockaddr_in server;
int rval;
unsigned long argp = 1;

struct timeval tv;
char errmsg[255];
fd_set fd;
fd_set readfd;
time_t t1, t2 ;
unsigned char * p;

memcpy(&(server.sin_addr), &ip, sizeof(server.sin_addr));
server.sin_port = htons(port);
server.sin_family = AF_INET;

clisock = socket(AF_INET, SOCK_STREAM, 0);
if (clisock < 0)
{
/* sockid == -1 */
sprintf(errmsg, "Client: socket() create. with error %d",
WSAGetLastError());
DebugLog(errmsg);
return FALSE;
}

ioctlsocket(clisock, FIONBIO, &argp);
FD_ZERO(&fd);
FD_ZERO(&readfd);

time(&t1) ;
t2 = t1 + 5 ;

while (WaitForSingleObject(gReadDataEvent, 30) != WAIT_OBJECT_0)
{
rval = connect(clisock, (struct sockaddr *) &server, sizeof(server)) ;
if (rval != 0)
{
FD_SET(clisock, &fd);
tv.tv_sec = 0; //gwcfg.timeout;
tv.tv_usec =5000L; //500000L;

FD_SET(clisock, &readfd);
tv.tv_sec = 0;
tv.tv_usec = 5000L;
if ((rval = select(0, &readfd, &fd, NULL, &tv)) <= 0)
{
if (rval == SOCKET_ERROR)
{
int Error = WSAGetLastError();
switch(Error)
{
case WSANOTINITIALISED:
break;
case WSAEFAULT: //currently ignore this condition
TRACE(_T("WARNING: MAX. Message Size exceeded\n"));
break;
case WSAENETDOWN:
break;
default:
{
TCHAR buffer[512];
wsprintf(buffer, _T("SendTo() returned %d"), Error);
}
break;
}
}
time(&t1) ;
if (t1 > t2)
{
/* time out */
closesocket(clisock);
p = (unsigned char *) &ip;
return FALSE ;
}
}
else
{
argp = 0; // none block
if (!AsyncMode)
ioctlsocket(clisock, FIONBIO, &argp);
return TRUE;
}
}
else
{
argp = 0; // none block
if (!AsyncMode)
ioctlsocket(clisock, FIONBIO, &argp);
return TRUE;
}
}
return FALSE;
#endif
}

cobra_chen 2012-06-13
  • 打赏
  • 举报
回复
server端去connect client端?
另不明白楼主代码是否是连续的代码,
或者只是代码片段?
建议楼主搜一些socket的文章看一看吧。
先要了解其工作机制。
磨刀不误砍柴工。

[Quote=引用 17 楼 的回复:]

引用 16 楼 的回复:

服务端无法修改么?
如果是这样,我只能提供一个思路。
在另外的线程或者进程去检查这个socket是否可写。
可以参考select
或者还有其他的检测手段。
-
最好的办法是服务端也做修改。
客户端长时间的阻塞也不是很好。
虽然阻塞模式会让编码变的简单,但是扩展性会差很多。
如果本来就要实现很简单的功能,阻塞模式也是相当好的。
关键看需要用来解……
[/Quote]
kapil 2012-06-13
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]

服务端无法修改么?
如果是这样,我只能提供一个思路。
在另外的线程或者进程去检查这个socket是否可写。
可以参考select
或者还有其他的检测手段。
-
最好的办法是服务端也做修改。
客户端长时间的阻塞也不是很好。
虽然阻塞模式会让编码变的简单,但是扩展性会差很多。
如果本来就要实现很简单的功能,阻塞模式也是相当好的。
关键看需要用来解决什么问题。

引用 15 楼……
[/Quote]

我已经把SERVER端修改了,是用JAVA写的

下面是在WHILE中添加的测试代码:


closesocket(clientSocket); // 手动关闭连接

// 接收数据的长度
receive_length = recv(clientSocket, recvbuf, sizeof(recvbuf), 0);

cout << receive_length << endl;

// 如果长度为0,就判断为连接断开,需要重新连接
if(receive_length < 0)
{
//closesocket(clientSocket);
cout << "reconnecting.." << endl;

connect(clientSocket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));//开始连接
}

调试后发现,SOCKET已经关闭,输出的长度为-1,但是仍然不能自动连接,是哪里的问题呢?
中国象棋的C++代码 #include "chess_zn.h" QTcpSocket * Chess_ZN::client = new QTcpSocket; QUndoStack * Chess_ZN::undoStack = new QUndoStack(); int Chess_ZN::second = 120; bool Chess_ZN::isTurn = false; Chess_ZN::Chess_ZN(QWidget *parent) : QWidget(parent) { init(); initElse(); } void Chess_ZN::initElse(){ treeitem = 1; timer=new QTimer; portmap=0; isConn = true; start = false; isTimer = false; isSearch = false; connect(timer,SIGNAL(timeout()),this,SLOT(stopWatch())); connect(wigettree[1],SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(getInfo(QTreeWidgetItem*))); connect(wigettree[0],SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(connectToHost_PK(QTreeWidgetItem*))); connect(client,SIGNAL(connected()),this,SLOT(connected())); //连接一旦断开 connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError ))); connect(client,SIGNAL(readyRead()),this,SLOT(readyRead())); peer = new PeerManager(this); peer->setServerPort(10001); items=wigettree[1]->currentItem(); item_pk=wigettree[0]->currentItem(); item_pk_info=wigettree[0]->currentItem(); connect(undoStack, SIGNAL(canUndoChanged(bool)),action2[8], SLOT(setEnabled(bool))); connect(undoStack, SIGNAL(canUndoChanged(bool)),action2[9], SLOT(setEnabled(bool))); connect(undoStack, SIGNAL(canUndoChanged(bool)),action2[10], SLOT(setEnabled(bool))); connect(undoStack, SIGNAL(canUndoChanged(bool)),action2[11], SLOT(setEnabled(bool))); connect(undoStack, SIGNAL(canUndoChanged(bool)),button[0], SLOT(setEnabled(bool))); connect(undoStack, SIGNAL(canUndoChanged(bool)),button[1], SLOT(setEnabled(bool))); connect(undoStack, SIGNAL(canUndoChanged(bool)),button[2], SLOT(setEnabled(bool))); connect(undoStack, SIGNAL(canUndoChanged(bool)),button[3], SLOT(setEnabled(bool))); timer->start(1000); createUndoView(); isChoose = true; tableeditor=new TableEditor("users"); } void Chess_ZN::createUndoView() { undoVie

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧