首页编程socketbind?Socket之bind、listen实现

socketbind?Socket之bind、listen实现

编程之家2023-11-0292次浏览

朋友们,socketbind和Socket之bind、listen实现是当今热门话题,但是它们的内涵和影响力可能会让人感到困惑。在本篇文章中,我将为你们揭示它们的本质和重要性,希望能够为你们带来新的认识。

socketbind?Socket之bind、listen实现

windows socket 编程:bind 错误码-1 如何解决

参考下面:

SOCKET server_socket;

SOCKADDR_IN internet_addr;

int ret, error, addr_len;

PROXY_SOCK_PARAM_T*_param;

HANDLE hThread;

socketbind?Socket之bind、listen实现

unsigned int thid;

//创建 socket

server_socket= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if(server_socket== INVALID_SOCKET)/*调用 socket不成功,返回 INVALID_SOCKET,

调用 WSAGetLastError()可查看错误代码*/

{

socketbind?Socket之bind、listen实现

error= WSAGetLastError();

// TODO:错误处理

return 0;

}

//进行 Socket绑定

internet_addr.sin_family= PF_INET;

internet_addr.sin_port= htons(PROXY_SERVER_PORT);

internet_addr.sin_addr.s_addr= htonl(INADDR_ANY);

ret= bind(server_socket,(SOCKADDR*)&internet_addr, sizeof(internet_addr));

if(ret!= 0)/* bind成功返回 0.否则返回 SOCKET_ERROR,调用 WSAGetLastError()可查看错误代码*/

{

error= WSAGetLastError();

closesocket(server_socket);

// TODO:错误处理

return 0;

}

//在 socket上进行监听

ret= listen(server_socket, 128);/* listen成功返回 0.否则返回 SOCKET_ERROR,

调用 WSAGetLastError()可查看错误代码*/

if(ret!= 0)

{

error= WSAGetLastError();

closesocket(server_socket);

// TODO:错误处理

return 0;

}

std::cout<<"[PROXY-SERVR]端口 5200监听启动..."<< std::endl;

//接收来自客户端的请求

for(;;)

{

//组织传递给新线程的数据结构

_param=(PROXY_SOCK_PARAM_T*)malloc(sizeof(PROXY_SOCK_PARAM_T));

_param->server_socket= server_socket;

addr_len= sizeof(_param->client_addr);

_param->client_socket= accept( _param->server_socket,

(SOCKADDR*)&(_param->client_addr),

&(addr_len));

if(_param->client_socket== INVALID_SOCKET)

{

error= WSAGetLastError();

// TODO:错误处理

} else{

//创建工作线程

hThread=(HANDLE)_beginthreadex(NULL, 0, server_work_thread,(void*)_param, 0,&thid);

if(hThread== INVALID_HANDLE_VALUE)

{

free(_param);

} else{

CloseHandle(hThread);

}

}

}

关于vc++写socket,bind出错

1.简单服务器

//#include<winsock2.h>

//#pragma comment(lib,"WS2_32.lib")

WSADATA wsd;

static UINT port=%%1;

UINT Listen(LPVOID pParam)

{

SOCKET sServer,sClient;

char buf[1024];

int retVal;

if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

{

return-1;//失败

}

sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

if(INVALID_SOCKET==sServer)

{

WSACleanup();

return-1;//创建套接字失败

}

SOCKADDR_IN addrServ;

addrServ.sin_family=AF_INET;

addrServ.sin_port=htons((short)pParam);

addrServ.sin_addr.s_addr=INADDR_ANY;

retVal=bind(sServer,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));

if(SOCKET_ERROR==retVal)

{

closesocket(sServer);

WSACleanup();

return-1;//绑定套接字失败

}

retVal=listen(sServer,1);

if(SOCKET_ERROR==retVal)

{

closesocket(sServer);

WSACleanup();

return-1;//开始监听失败

}

sockaddr_in addrClient;

int addrClientlen=sizeof(addrClient);

sClient=accept(sServer,(sockaddr FAR*)&addrClient,&addrClientlen);

if(INVALID_SOCKET==sClient)

{

closesocket(sServer);

WSACleanup();

return-1;//开始接受客户端连接失败

}

ZeroMemory(buf,sizeof(buf));

retVal=recv(sClient,buf,sizeof(buf),0);

if(SOCKET_ERROR==retVal)

{

closesocket(sServer);

closesocket(sClient);

WSACleanup();

return-1;//接收数据失败

}

CString%%2(buf);

closesocket(sServer);

closesocket(sClient);

WSACleanup();

return 0;

}

CWinThread*pThread=AfxBeginThread(Listen,&port);

2.简单客户端

//#include<winsock2.h>

//#pragma comment(lib,"WS2_32.lib")

WSADATA wsd;

SOCKET sHost;

SOCKADDR_IN servAddr;

char buf[1024];

int retVal;

if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

{

return-1;//失败

}

sHost=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

if(INVALID_SOCKET==sHost)

{

WSACleanup();

return-1;//创建套接字失败

}

servAddr.sin_family=AF_INET;

servAddr.sin_addr.s_addr=inet_addr(%%3);

servAddr.sin_port=htons((short)%%2);

int nServAddlen=sizeof(servAddr);

retVal=connect(sHost,(LPSOCKADDR)&servAddr,sizeof(servAddr));

if(SOCKET_ERROR==retVal){

closesocket(sHost);

WSACleanup();

return-1;//连接服务器失败

}

ZeroMemory(buf,sizeof(buf));

strcpy(buf,%%3);

retVal=send(sHost,buf,sizeof(buf),0);

if(SOCKET_ERROR==retVal)

{

closesocket(sHost);

WSACleanup();

return-1;//向服务器发送数据失败

}

closesocket(sHost);

WSACleanup();

3.获得本机IP

//#include<winsock2.h>

//#pragma comment(lib,"WS2_32.lib")

WSADATA wsd;

if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

{

return-1;//失败

}

char szHostname[100],szHostaddress[200];

if(gethostname(szHostname,sizeof(szHostname))!=SOCKET_ERROR)

{

HOSTENT*pHostEnt=gethostbyname(szHostname);

if(pHostEnt!=NULL){

sprintf(szHostaddress,"%d.%d.%d.%d",

( pHostEnt->h_addr_list[0][0]&0x00ff),

( pHostEnt->h_addr_list[0][1]&0x00ff),

( pHostEnt->h_addr_list[0][2]&0x00ff),

( pHostEnt->h_addr_list[0][3]&0x00ff));

}

}

else

return;

CString%%1(szHostaddress);

4.端对端通信

//#include<winsock2.h>

//#pragma comment(lib,"WS2_32.lib")

WSADATA wsd;

SOCKET s;

char buf[1024];

if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

{

return-1;//失败

}

s=socket(AF_INET,SOCK_DGRAM,0);

if(s==INVALID_SOCKET)

{

WSACleanup();

return-1;//创建套接字失败

}

SOCKADDR_IN servAddr;

servAddr.sin_family=AF_INET;

servAddr.sin_addr.s_addr=inet_addr(%%1);

servAddr.sin_port=htons(INADDR_ANY);

if(bind(s,(SOCKADDR*)&servAddr,sizeof(SOCKADDR_IN))==SOCKET_ERROR)

{

closesocket(s);

WSACleanup();

return-1;//绑定套接字失败

}

int nServAddrlen=sizeof(servAddr);

ZeroMemory(buf,sizeof(buf));

if(recvfrom(s,buf,sizeof(buf),0,(SOCKADDR*)&servAddr,&nServAddrlen)==SOCKET_ERROR)

{

closesocket(s);

WSACleanup();

return-1;//接收数据失败

}

CString%%2(buf);

ZeroMemory(buf,sizeof(buf));

strcpy(buf,%%3);

SOCKADDR_IN clientAddr;

clientAddr.sin_family=AF_INET;

clientAddr.sin_addr.s_addr=inet_addr(%%4);

clientAddr.sin_port=htons((short)%%5);

int nClientlen=sizeof(clientAddr);

if(sendto(s,buf,sizeof(buf),0,(SOCKADDR*)&clientAddr,nClientlen)==SOCKET_ERROR)

{

closesocket(s);

WSACleanup();

return-1;//向服务器发送数据失败

}

closesocket(s);

WSACleanup();

5.点对点通信

//#include<winsock2.h>

//#pragma comment(lib,"WS2_32.lib")

WSADATA wsd;

SOCKADDR_IN addrServ,addrServ2;

SOCKET sServer,sClient,sHost;

int retVal;

sockaddr_in addrClient;

char buf[1024];

static UINT port=%%2;

BOOL listenerRun=TRUE;

UINT Listen(LPVOID pParam)

{

addrServ.sin_family=AF_INET;

addrServ.sin_port=htons((UINT)pParam);

addrServ.sin_addr.s_addr=INADDR_ANY;

retVal=bind(sServer,(LPSOCKADDR)&addrServ,sizeof(SOCKADDR_IN));

if(SOCKET_ERROR==retVal)

{

closesocket(sServer);

WSACleanup();

return-1;//绑定套接字失败

}

retVal=listen(sServer,1);

if(SOCKET_ERROR==retVal)

{

closesocket(sServer);

WSACleanup();

return-1;//开始监听失败

}

int addrClientlen=sizeof(addrClient);

sClient=accept(sServer,(sockaddr FAR*)&addrClient,&addClientlen);

if(INVALID_SOCKET==sClient)

{

closesocket(sServer);

WSACleanup();

return-1;//接收客户端请求失败

}

while(listenerRun)

{

ZeroMemory(buf,sizeof(buf));

retVal=recv(sClient,buf,sizeof(buf));

if(SOCKET_ERROR==retVal)

{

closesocket(sServer);

closesocket(sClient);

WSACleanup();

return-1;//接收客户端数据失败

}

CString%%4(buf);

}

}

if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

{

return-1;//失败

}

sServer=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

if(INVALID_SOCKET==sServer)

{

WSACleanup();

return-1;//创建套接字失败

}

CWinThread*pThread=AfxBeginThread(Listen,&port);

sHost=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

if(INVALID_SOCKET==sHost)

{

WSACleanup();

return-1;//创建套接字失败

}

servAddr2.sin_family=AF_INET;

servAddr2.sin_addr.s_addr=inet_addr(%%1);

servAddr.sin_port=htons((short)%%3);

int nServerAddrlen=sizeof(servAddr2);

retVal=connect(sHost,(LPSOCKADDR)&servAddr2,sizeof(servAddr2));

if(SOCKET_ERROR==retVal)

{

closesocket(sHost);

WSACleanup();

return-1;//连接失败

}

zeroMemory(buf,sizeof(buf));

strcpy(buf,%%5);

retVal=send(sHost,buf,sizeof(buf),0);

if(SOCKET_ERROR==retVal)

{

closesocket(sHost);

WSACleanup();

return-1;//向发送数据失败

}

listenerRun=FALSE;

DWORD dwExitCode;

::GetExitCodeThread(pThread->m_hThread,&dwExitCode);

pThread=null;

closesocket(sServer);

closesocket(sClient);

closesocket(sHost);

WSACleanup();

Socket之bind、listen实现

bind()函数的使用方法很简单,但是它是怎么实现的呢?

本文将从应用层出发,沿着网络协议栈,分析了bind()、 listen()的系统调用、Socket层实现,以及它的TCP层实现。

应用层

int bind(int sockfd, const struct sockaddr*my_addr, socklen_t addrlen);

bind() gives the socket sockfd the local address my_addr.

给socket描述符绑定IP和端口,一般服务器才需要。端口号的范围为0~ 65535。调用bind()时,一般不要把端口号置为小于1024的值,因为1到1023是保留端口号。

系统调用

bind()是由glibc提供的,声明位于include/sys/socket.h中,实现位于sysdeps/mach/hurd/bind.c中,主要是用来从用户空间进入名为sys_socketcall的系统调用,并传递参数。sys_scoketcall()实际上是所有socket函数进入内核空间的共同入口。

在sys_socketcall()中会调用sys_bind()。

经过了socket层的总入口sys_socketcall(),现在进入sys_bind()。

经过了socket层的总入口sys_socketcall(),现在进入sys_bind()。

通过文件描述符,找到对应的file结构。

通过file结构,找到对应的socket结构。

把用户空间的socket地址复制到内核空间,同时检查是否合法,成功返回0。

socket层

SOCK_STREAM套接口的socket层操作函数集实例为inet_stream_ops,其中绑定函数为inet_bind()。

socket层做的主要事情为合法性检查、绑定IP地址,而真正的端口绑定是在TCP层进行的。

应用层

int listen(int sockfd, int backlog);

Accept incoming connections and a queue limit for incoming connections.

backlog的定义

Now it specifies the queue length for completely established sockets waiting to be accepted,

instead of the number of incomplete connection requests. The maximum length of the queue

for incomplete sockets can be set using the tcp_max_syn_backlog sysctl. When syncookies

are enabled there is no logical maximum length and this sysctl setting is ignored.

全连接队列的最大长度:

backlog保存的是完成三次握手、等待accept的全连接,而不是半连接。

负载不高时,backlog不用太大。(For complete connections)

系统最大的、未处理的全连接数量为:min(backlog, somaxconn),net.core.somaxconn默认为128。

半连接队列的最大长度:

tcp_max_syn_backlog默认值为256。(For incomplete connections)

当使用SYN Cookie时,这个参数变为无效。

半连接队列的最大长度为backlog、somaxconn、tcp_max_syn_backlog的最小值。

listen()是由glibc提供的,声明位于include/sys/socket.h中,实现位于sysdeps/mach/hurd/listen.c中,主要是用来从用户空间进入名为sys_socketcall的系统调用,并传递参数。sys_socketcall()实际上是所有socket函数进入内核空间的共同入口。

在sys_socketcall()中会调用sys_listen()。

经过了socket层的总入口sys_socketcall(),现在进入sys_listen()。

SOCK_STREAM套接口的socket层操作函数集实例为inet_stream_ops,其中监听函数为inet_listen()。

检查套接口的状态、当前连接的状态是否合法,然后调用inet_csk_listen_start()启动监听。

启动监听时,做的工作主要包括:

listen_sock结构用于保存SYN_RECV状态的连接请求块,所以也叫半连接队列。

(1)创建

queue是连接请求控制块,nr_table_entries是半连接的最大个数,即backlog。

(2)销毁

销毁连接请求块中的listen_sock实例,释放半连接队列。

socket中bind函数绑定的IP是什么

所谓bind,就是指绑定本地接受端口。

指定ip,是为了分辨多ip主机。

bind是服务端调用的函数,绑定的是服务端的IP,假设服务端有多个网卡,即会有多个IP,这个时候我们可以选择用bind绑定其中一个IP,那么服务端只接收该IP上某端口的数据。

如果bind绑定的是INADDR_ANY,即表示所有发送到服务器的这个端口,不管是哪个网卡/哪个IP地址接收到的数据,都由这个服务端进程进行处理。

非常感谢您的阅读!我们希望本文对于解决您关于socketbind的问题提供了一些有价值的信息。如果您还有其他疑问,我们将很乐意为您提供进一步的帮助。

百度关键词优化软件 网店关键词优化软件有哪些阿城网 东北阿城怎么样