您的位置:首页 > 理论基础 > 计算机网络

蔡军生先生第二人生的源码分析(二十九)Windows网络初始化

2008-05-17 15:11 465 查看
上面已经介绍怎么样通过网络发送数据了,但心里又有一个问题,就是网络是怎么样进行初始化,才能发送数据呢?怎么样创建Windows下的UDP协议的呢?现在就来分析这段初始化的代码。
#001 S32 start_net(S32& socket_out, int& nPort)
#002 {
#003 // Create socket, make non-blocking
#004 // Init WinSock
#005 int nRet;
#006 int hSocket;
#007
#008 int snd_size = SEND_BUFFER_SIZE;
#009 int rec_size = RECEIVE_BUFFER_SIZE;
#010 int buff_size = 4;
#011

下面初始化Windows网络通讯库,版本是2.2的。
#012 // Initialize windows specific stuff
#013 if(WSAStartup(0x0202, &stWSAData))
#014 {
#015 S32 err = WSAGetLastError();
#016 WSACleanup();
#017 llwarns << "Windows Sockets initialization failed, err " << err << llendl;
#018 return 1;
#019 }
#020

创建一个UDP的socket。
#021 // Get a datagram socket
#022 hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0);
#023 if (hSocket == INVALID_SOCKET)
#024 {
#025 S32 err = WSAGetLastError();
#026 WSACleanup();
#027 llwarns << "socket() failed, err " << err << llendl;
#028 return 2;
#029 }
#030

设置UDP监听的端口和任何IP地址。
#031 // Name the socket (assign the local port number to receive on)
#032 stLclAddr.sin_family = AF_INET;
#033 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
#034 stLclAddr.sin_port = htons(nPort);
#035
#036 S32 attempt_port = nPort;
#037 llinfos << "attempting to connect on port " << attempt_port << llendl;
#038 nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
#039

如果绑定出错,尝试使用其它端口进行绑定。
#040 if (nRet == SOCKET_ERROR)
#041 {
#042 // If we got an address in use error...
#043 if (WSAGetLastError() == WSAEADDRINUSE)
#044 {
#045 // Try all ports from PORT_DISCOVERY_RANGE_MIN to PORT_DISCOVERY_RANGE_MAX
#046 for(attempt_port = PORT_DISCOVERY_RANGE_MIN;
#047 attempt_port <= PORT_DISCOVERY_RANGE_MAX;
#048 attempt_port++)
#049 {
#050 stLclAddr.sin_port = htons(attempt_port);
#051 llinfos << "trying port " << attempt_port << llendl;
#052 nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
#053
#054 if (!(nRet == SOCKET_ERROR &&
#055 WSAGetLastError() == WSAEADDRINUSE))
#056 {
#057 break;
#058 }
#059 }
#060
#061 if (nRet == SOCKET_ERROR)
#062 {
#063 llwarns << "startNet() : Couldn't find available network port." << llendl;
#064 // Fail gracefully here in release
#065 return 3;
#066 }
#067 }
#068 else
#069 // Some other socket error
#070 {
#071 llwarns << llformat("bind() port: %d failed, Err: %d/n", nPort, WSAGetLastError()) << llendl;
#072 // Fail gracefully in release.
#073 return 4;
#074 }
#075 }
#076

下面获取绑定的端口和IP地址。
#077 sockaddr_in socket_address;
#078 S32 socket_address_size = sizeof(socket_address);
#079 getsockname(hSocket, (SOCKADDR*) &socket_address, &socket_address_size);
#080 attempt_port = ntohs(socket_address.sin_port);
#081
#082 llinfos << "connected on port " << attempt_port << llendl;
#083 nPort = attempt_port;
#084

下面设置UDP的socket为非阻塞收发数据的方式。
#085 // Set socket to be non-blocking
#086 unsigned long argp = 1;
#087 nRet = ioctlsocket (hSocket, FIONBIO, &argp);
#088 if (nRet == SOCKET_ERROR)
#089 {
#090 printf("Failed to set socket non-blocking, Err: %d/n",
#091 WSAGetLastError());
#092 }
#093

设置接收和发送的数据缓冲区的大小。
#094 // set a large receive buffer
#095 nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
#096 if (nRet)
#097 {
#098 llinfos << "Can't set receive buffer size!" << llendl;
#099 }
#100
#101 nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
#102 if (nRet)
#103 {
#104 llinfos << "Can't set send buffer size!" << llendl;
#105 }
#106
#107 getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
#108 getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
#109
#110 llinfos << "startNet - receive buffer size : " << rec_size << llendl;
#111 llinfos << "startNet - send buffer size : " << snd_size << llendl;
#112

下面初始化发送到的目的地址。
#113 // Setup a destination address
#114 char achMCAddr[MAXADDRSTR] = " "; /* Flawfinder: ignore */
#115 stDstAddr.sin_family = AF_INET;
#116 stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr);
#117 stDstAddr.sin_port = htons(nPort);
#118
#119 socket_out = hSocket;
#120 return 0;
#121 }

在这个函数里,先初始化网络库,并且版本为2.2的。接着,创建一个UDP的socket,然后绑定端口和IP地址。最后设置连接方式为非阻塞的方式,设置接收和发送缓冲区为更大的数量。通过这个函数就初始化第二人生的网络通讯了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐