关于socket问题(在线等)

delphiwcdj 2009-10-12 04:34:53

SOCKET s_d=accept(sock,(sockaddr*)&addrClient,&nLen);//返回会话套接字
if(sock==INVALID_SOCKET)
{
//错误处理
printf("accept wrong\n");
}

我要问大家的是:

我写了一个win32控制台下的socket tcp通信,server端执行到accept会阻塞,直到接收到client端的信息。
问题:
(1)sever端执行到accept会阻塞,那么什么时候会执行下面的if判断?
(2)我想实现在win32控制台下,server端可以监听多个client端的连接请求?我认为,可以用一个单独的子线程来负责accept的工作,而在主线程中来完成不同client套接字的会话工作。不知道我这个想法是否正确(MFC下好像是怎么做的,但是它都封装起来了,如何实现多线程的看不到)。如果上面想法正确,请大家给个代码框架,我对多线程还不是很熟。谢了!

祝大家天天愉快!
...全文
242 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Garfield 2009-10-13
  • 打赏
  • 举报
回复
另外,msdn中关于accept函数的return value一栏下面列出了WSAGetLastError可能返回的错误值
你就可以反向推断出,什么情况下会出现socket_error的返回值。
如果你是用的很正常的,不会返回error那是当然的。
Garfield 2009-10-13
  • 打赏
  • 举报
回复
1.我想问的是什么时候会返回INVALID_SOCKET,这种情况我没有测试出来
---
你可以试一下accept第一个参数传一个非法socket句柄,立刻就会返回。


2.accept返回的套接字是可以通过参数访问,并且在线程中将其释放,但是我不知道,主线程中的监听套接字何时才能释放呢?程序一直在while(1)中循环。
---
你看这个程序用while(1)明显是打算一直作为一个永不退出的服务器运行,所以他没处理退出的情况,等待“他杀”,所以省略了释放的代码,让被杀的时候系统自行回收该进程资源。
delphiwcdj 2009-10-13
  • 打赏
  • 举报
回复
谢谢大家的回答!


SOCKET s_d=accept(sock,(sockaddr*)&addrClient,&nLen);//返回会话套接字
//if(sock==INVALID_SOCKET)
if(s_d==INVALID_SOCKET)//我这里写错了,应该用返回的套接字判断的
{
//错误处理
printf("accept wrong\n");
}


针对上面的回答:
hairetz:
1.什么时候会执行if,首先你是阻塞accept,那自然要有其他主机尝试connect,accept才会返回一次。
---
我想问的是什么时候会返回INVALID_SOCKET,这种情况我没有测试出来

Garfield:
2,
那段代码不就是在子线程访问么,做参数传进去了而已,当然你可也以做成全局变量用。
wsacleanup一般在最后调用。
---
accept返回的套接字是可以通过参数访问,并且在线程中将其释放,但是我不知道,主线程中的监听套接字何时才能释放呢?程序一直在while(1)中循环。

while(1)
{
AcceptSocket=SOCKET_ERROR;
while(AcceptSocket==SOCKET_ERROR)
{
AcceptSocket=accept(m_socket,NULL,NULL);
}
printf("Client Connected.\n");

DWORD dwThreadId;
HANDLE hThread;

hThread=CreateThread(NULL,NULL, AnswerThread,
(LPVOID)AcceptSocket,0,&dwThreadId);
//...
}


不知道我是否说清楚了。谢了!
Garfield 2009-10-13
  • 打赏
  • 举报
回复
5#说完了。
recv >0, data
recv = 0, graceful close
recv = -1, error (connection reset)

>to 1L:
>在main中定义的AcceptSocket,为什么不能在子线程中访问呢?子线程不是可以访问主线程的资源的么。
>如果访问不了,请问又如何在main中close掉AcceptSocket和m_sock呢?

那段代码不就是在子线程访问么,做参数传进去了而已,当然你可也以做成全局变量用。


wsacleanup一般在最后调用。

  • 打赏
  • 举报
回复
[Quote=引用楼主 delphiwcdj 的回复:]
C/C++ code
SOCKET s_d=accept(sock,(sockaddr*)&addrClient,&nLen);//返回会话套接字if(sock==INVALID_SOCKET)
{//错误处理 printf("accept wrong\n");
}
我要问大家的是:

我写了一个win32控制台下的socket tcp通信,server端执行到accept会阻塞,直到接收到client端的信息。
问题:
(1)sever端执行到accept会阻塞,那么什么时候会执行下面的if判断?
(2)我想实现在win32控制台下,server端可以监听多个client端的连接请求?我认为,可以用一个单独的子线程来负责accept的工作,而在主线程中来完成不同client套接字的会话工作。不知道我这个想法是否正确(MFC下好像是怎么做的,但是它都封装起来了,如何实现多线程的看不到)。如果上面想法正确,请大家给个代码框架,我对多线程还不是很熟。谢了!

祝大家天天愉快!
[/Quote]
1.什么时候会执行if,首先你是阻塞accept,那自然要有其他主机尝试connect,accept才会返回一次。

2.你就是想写个并发服务器,很多办法啊。
一般有多进程,多线程,io复用模型。
想看实现,找本linux网络编程实例看下,很清楚的。
cmo_lyl 2009-10-13
  • 打赏
  • 举报
回复
学习,UP~~
delphiwcdj 2009-10-13
  • 打赏
  • 举报
回复
up
Wind_Runner 2009-10-13
  • 打赏
  • 举报
回复
下面的if判断应该是socket的时候就做了的,这是服务器的监听套接字,监听连接的,不应该此时才做判断
delphiwcdj 2009-10-13
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 garfield 的回复:]
你看这个程序用while(1)明显是打算一直作为一个永不退出的服务器运行,所以他没处理退出的情况,等待“他杀”,所以省略了释放的代码,让被杀的时候系统自行回收该进程资源。
[/Quote]
如果我们不手动调用,比如下面的代码:

nResult=closesocket(ListenSocket);
if(nResult==SOCKET_ERROR)
{
printf("closesocket() failed\n");
}
WSACleanup();

系统会帮我们回收这部分资源吗?不知道是否有相关文档说明
delphiwcdj 2009-10-13
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 garfield 的回复:]
另外,msdn中关于accept函数的return value一栏下面列出了WSAGetLastError可能返回的错误值
你就可以反向推断出,什么情况下会出现socket_error的返回值。
如果你是用的很正常的,不会返回error那是当然的。
[/Quote]
谢谢你!明白了。
由于MSDN太大了,我一直没有安装,有问题了一般都是g一下,所以很不全面。
请问现在用的MSDN是哪个版本的啊
delphiwcdj 2009-10-12
  • 打赏
  • 举报
回复
to 1L:
在main中定义的AcceptSocket,为什么不能在子线程中访问呢?子线程不是可以访问主线程的资源的么。
如果访问不了,请问又如何在main中close掉AcceptSocket和m_sock呢?

谢谢!
delphiwcdj 2009-10-12
  • 打赏
  • 举报
回复
to 1L:

看了你的代码,有个问题是:sever什么时候调用WSACleanup()呢?
lsldd 2009-10-12
  • 打赏
  • 举报
回复
看recv返回值;MSDN上说:
If no error occurs, recv returns the number of bytes received.
收到数据,返回数据长度。

If the connection has been gracefully closed, the return value is zero.
正常关闭,返回0

Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
其余情况则是非正常关闭,可以配合WSAGetLastError查询具体原因。
kxalpah 2009-10-12
  • 打赏
  • 举报
回复
1.sever端执行到accept会阻塞,那么什么时候会执行下面的if判断?
当程序链接到一个client是会执行这段代码
2.可以设定一个数组用来保存当前已连接的套接字,每当主线程链接一个新的client时更新一次,然后在子线程中使用死循环遍历这个数组,不停地准备接收
至善者善之敌 2009-10-12
  • 打赏
  • 举报
回复
SOCKET m_hSocket;

if(m_hSocket != NULL)
{
//如果已经创建了套接字先关闭原来的
closesocket(m_hSocket);
m_hSocket = NULL;
}
delphiwcdj 2009-10-12
  • 打赏
  • 举报
回复
谢了,一会儿我看一下。

还有个问题:
如何判断client的socket已经调用closesocket?是从recv的返回值判断吗?具体是什么值
wanjingwei 2009-10-12
  • 打赏
  • 举报
回复
这有个例子

#include "StdAfx.h"
#include <stdio.h>

DWORD WINAPI AnswerThread(LPVOID lparam)
{
SOCKET ClientSocket=(SOCKET)(LPVOID)lparam;

int bytesRecv;
char sendbuf[32]="";
char recvbuf[32]="";

while(1)
{
bytesRecv=SOCKET_ERROR;
for(int i=0;i<(int)strlen(recvbuf);i++)
{ recvbuf[i]=´\0´; }


while(bytesRecv==SOCKET_ERROR)
{ //Receiving Data
bytesRecv=recv(ClientSocket,recvbuf,32,0);
}



//Write your processing code here
send(ClientSocket,recvbuf,strlen(recvbuf),0);
printf("%s\n",recvbuf);
}
return 0;
}

int main(int argc,char* argv[])
{
//initialize Winsock
WSADATA wsaData;
int iRet=WSAStartup(MAKEWORD(2,2),&wsaData);
if(iRet!=NO_ERROR)
printf("Error at WSAStartup()\n");

//create a socket
SOCKET m_socket;
m_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(m_socket==INVALID_SOCKET)
{
printf("Error at socket():%ld\n",WSAGetLastError());
WSACleanup();
return 0;
}

//bind a socket
sockaddr_in service;
service.sin_family=AF_INET;
service.sin_addr.s_addr=inet_addr("172.16.3.250");
service.sin_port=htons(2501);

if(bind(m_socket,(SOCKADDR*)&service,sizeof(service))==SOCKET_ERROR)
{
printf("bind() failed.\n");
closesocket(m_socket);
return 0;
}
else
printf("bind OK.\n");

//listen on a socket
if(listen(m_socket,20)==SOCKET_ERROR)
printf("Error listening on socket.\n");
else
printf("listening ok.\n");

//accept a connection
SOCKET AcceptSocket;

printf("Waiting for a client to connect...\n");
while(1)
{
AcceptSocket=SOCKET_ERROR;
while(AcceptSocket==SOCKET_ERROR)
{
AcceptSocket=accept(m_socket,NULL,NULL);
}
printf("Client Connected.\n");

DWORD dwThreadId;
HANDLE hThread;

hThread=CreateThread(NULL,NULL, AnswerThread,
(LPVOID)AcceptSocket,0,&dwThreadId);
if(hThread==NULL)
{
printf("CreatThread AnswerThread() failed.\n");
}
else
{
printf("CreateThread OK.\n");
}
}
return 0;
}

64,282

社区成员

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

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