socket 中listen函数参数的解释

3 篇文章 0 订阅
在写socket程序时,作为服务端t通常要使用listen来说明允许并发连接的个数,百度上对listen函数的说明为:
 #include <winsock.h>
  int PASCAL FAR listen( SOCKET s, int backlog);
  S:用于标识一个已捆绑未连接套接口的描述字。
  backlog:等待连接队列的最大长度。
(详细解释,请看百度百科:http://baike.baidu.com/view/569204.htm)
listen()的第二个参数为等待连接队列的最大长度,其实这个的意思是说,在某一时刻(注意,是某一时刻)同时允许最多有backlog个客户端要和服务器端进行连接,而不是像有些人想的那样,只能允许backlog个服务端与客户端进行连接; 


下面是我写的一个例子,可以做很好的说明:
开发环境: VC6.0

server
// Socket_server.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

#define PORT_SERVER 7777
#define NUM_CLIENTS 10
#define MAX_LENGTH  512

struct _socket_{
SOCKET socket_client;
};

_socket_ str_socket;

WORD g_ThreadCount = 0;
DWORD g_mythreadId = 0;

DWORD WINAPI ThreadProc(LPVOID lParam)
{
WORD threadCount = g_ThreadCount++;
printf("Server %d.\n",threadCount);

SOCKET sock_client = ((_socket_ *)lParam)->socket_client;

/* 设置发送/接受数据超时时间 
struct timeval t;
t.tv_sec = 1; //1 秒
//char nNetTimeout = 10;//1秒
setsockopt(sock_client,SOL_SOCKET,SO_RCVTIMEO,(char*)&t,sizeof(struct timeval));
setsockopt(sock_client,SOL_SOCKET,SO_SNDTIMEO,(char*)&t,sizeof(struct timeval));
*/
Sleep(50000);

//关闭socket
closesocket(sock_client);

return 0L;
}

int main(int argc, char* argv[])
{
printf("Start up tcp server.\n");
WSADATA wsaData;
WORD sockVersion = MAKEWORD(2, 0);

int _error;

_error = WSAStartup(sockVersion, &wsaData);

if ( _error != 0 )
{
printf("Failed to retrive socket version.\n");
return 0;
}

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

if (INVALID_SOCKET == sock_sev)
{
printf("Invalid socket.\n");
WSACleanup();
return 0;
}

SOCKADDR_IN addr_sev;
addr_sev.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addr_sev.sin_family = AF_INET;
addr_sev.sin_port = htons(PORT_SERVER);

if (SOCKET_ERROR == bind(sock_sev, (SOCKADDR *)&addr_sev, sizeof(SOCKADDR)))
{
printf("Failed to bind.\n");
WSACleanup();
return 0;
}

if (SOCKET_ERROR == listen(sock_sev, NUM_CLIENTS)) //最多允许10个链接并发链接
{
printf("Failed to listen.\n");
WSACleanup();
return 0;
}

SOCKADDR_IN addr_client;
int nAddrLen = sizeof(SOCKADDR);
HANDLE hThread = 0;

//for(int i = 0; i < NUM_CLIENTS; i++ )
while(true)
{
SOCKET sock_client;
sock_client = accept(sock_sev, (SOCKADDR *)&addr_client, &nAddrLen); //从tcp缓存中读取链接请求,然后进行处理
if( INVALID_SOCKET == sock_client )
{
printf("Failed to accept From Client.\n");
closesocket(sock_client);
continue;
}

str_socket.socket_client = sock_client;
hThread = ::CreateThread(NULL,   //起一个线程进行socket处理
0,
ThreadProc,
&str_socket,
0,
&g_mythreadId);

if( hThread != NULL)
{
CloseHandle(hThread);
hThread = NULL;
}
}

closesocket(sock_sev);
WSACleanup();

Sleep(50000);
system("pause");

return 0;
}


/client///

// Socket_client.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include <winsock2.h>
#include <stdlib.h>

#define PORT_SERVER 7777
#define MAX_LENGTH 512
#define CLIENTCOUNT 20

WORD g_ThreadCount = 0;
DWORD g_mythreadId = 0;

static UINT g_uCount = 0;
HANDLE hThread = 0;


//客户端,用来与服务端进行连接
//只与服务端进行连接,不与服务端进行通信
DWORD WINAPI ThreadProc(LPVOID lParam)
{
printf("Thread %d \n",g_uCount++);

WSADATA  wsaData;
WORD sockVersion = MAKEWORD(2,0);
if( 0 != WSAStartup(sockVersion,&wsaData) )
{
printf("Failed to retrive socket version.\n");
return 0;
}

SOCKET sock_client = INVALID_SOCKET;
sock_client = socket(AF_INET, SOCK_STREAM,0);

if (INVALID_SOCKET == sock_client)
{
printf("Invalid socket. ErrorCode[%d]\n",WSAGetLastError());
WSACleanup();
return 0;
}
SOCKADDR_IN addr_sev;
addr_sev.sin_family = AF_INET;
addr_sev.sin_port = htons(PORT_SERVER);
addr_sev.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (SOCKET_ERROR == connect( sock_client, (SOCKADDR *)&addr_sev, sizeof(SOCKADDR)))
{
printf("Failed to connect. ErrorCode[%d]\n",WSAGetLastError());
WSACleanup();
return 0;
}
Sleep(5000);
closesocket(sock_client);
WSACleanup();
return 0;
}

int main(int argc, char* argv[])
{
printf("Start up  Client!\n");

for(int i = 0; i < CLIENTCOUNT; i++)  //创建20个链
{
hThread = ::CreateThread(NULL,
0,
ThreadProc,
NULL,
0,
&g_mythreadId);

if( hThread != NULL)
{
CloseHandle(hThread);
hThread = NULL;
}
}
system("pause");
return 0;
}



虽然服务端在listen中设置了10,但是客户端的这20个链接都可以与服务端进行连接通信,因为这20个链接并不是在同一时刻发生的

转载自:http://blog.163.com/zhangjinqing1234@126/blog/static/30730260201010392119467/
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值