Winsock 学习笔记(三)Winsock Server Application

Maybe the significant difference between Winsock and java socket until now is that java distinguish ServerSocket from Socket while in Winsock there is only a SOCKET.


In general, The code of server side is similar with the code of client.

Here it is.


#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_PORT "27015"//define the port on server by default which the client will connect to
#define DEFAULT_BUFLEN 512

int main(int argc, char *argv[]){
	WSADATA wsaData;

	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0){
		printf("WSAStartup failed: %d\n", iResult);
		return 1;
	}

	struct addrinfo *result = NULL, *ptr = NULL, hints;

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_INET; //specify the IPv4 address family
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	//AI_PASSIVE flag indicates the caller intends to use the returned socket address structure in a call to the bind function.
	//When the AI_PASSIVE flag is set and nodename parameter to the getaddrinfo function is a NULL pointer, 
	//the IP address portion of the socket address structure is set to INADDR_ANY for IPv4 addresses or IN6ADDR_ANY_INIT for IPv6 addresses.
	hints.ai_flags = AI_PASSIVE; 

	// Resolve the local address and port to be used by the server
	iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
	if (iResult != 0){
		printf("getaddrinfo failed: %d\n", iResult);
		WSACleanup();
		return 1;
	}

	SOCKET ListenSocket = INVALID_SOCKET;

	ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

	if (ListenSocket == INVALID_SOCKET){
		printf("Error at socket(): %ld\n", WSAGetLastError());
		freeaddrinfo(result);
		WSACleanup();
		return 1;
	}

	//to bind a socket
	//Setup the TCP listening socket
	iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
	if (iResult == SOCKET_ERROR){
		printf("bind failed with error: %d\n", WSAGetLastError());
		freeaddrinfo(result);
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	//the address information returned by the getaddrinfo function is no longer needed.
	freeaddrinfo(result);

	//Call the listen function, passing as parameters the created socket and a value for the backlog, 
	//maximum length of the queue of pending connections to accept.
	//"SOMAXCONN" is a special constant(0x7fffffff) that instructs the Winsock provider for this socket
	//to allow a maximum reasonable number of pending connections in the queue. 
	if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR){
		printf("Listen failed with error: %ld\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	//Create a temporary SOCKET object called ClientSocket for accepting connections from clients.
	SOCKET ClientSocket = INVALID_SOCKET;

	//Accept a client socket
	//When the client connection has been accepted, a server application would normally pass the accepted client socket (the ClientSocket variable in the above sample code) 
	//to a worker thread or an I/O completion port and continue accepting additional connections. In this basic example, the server continues to the next step.
	ClientSocket = accept(ListenSocket, NULL, NULL);
	if (ClientSocket == INVALID_SOCKET){
		printf("accept failed: %d\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	//Note  On Unix systems, a common programming technique for servers was for an application to listen for connections. When a connection was accepted, 
	//the parent process would call the fork function to create a new child process to handle the client connection, inheriting the socket from the parent.
	//This programming technique is not supported on Windows, since the fork function is not supported.
	//This technique is also not usually suitable for high-performance servers, since the resources needed to create a new process are much greater than those needed for a thread.

	char recvbuf[DEFAULT_BUFLEN];
	int iSendResult;
	int recvbuflen = DEFAULT_BUFLEN;

	//Receive until the peer shuts down the connetion
	do{
		iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
		if (iResult > 0){
			printf("Bytes received: %d\n", iResult);

			//Echo the buffer back to the sender
			iSendResult = send(ClientSocket, recvbuf, iResult, 0);
			if (iSendResult == SOCKET_ERROR){
				printf("send failed: %d\n", WSAGetLastError());
				closesocket(ClientSocket);
				WSACleanup();
				return 1;
			}
			printf("Bytes sent: %d\n", iSendResult);
		}
		else if (iResult == 0)
			printf("Connection closing...\n");
		else{
			printf("recv failed: %d\n", WSAGetLastError());
			closesocket(ClientSocket);
			WSACleanup();
			return 1;
		}
	} while (iResult > 0);

	closesocket(ClientSocket);
	WSACleanup();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值