Winsock网络编程笔记:基于UDP的Server

每次写网络程序都必须编写代码载入和释放winsock库,为了以后方便使用,我们将封装一个CInitSock类来管理Winsock库:

// initsock.h文件
 
#include <winsock2.h>
#pragma comment(lib, "WS2_32")    // 链接到WS2_32.lib
 
class CInitSock        
{
public:
    CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
    {
        // 初始化WS2_32.dll
        WSADATA wsaData;
        WORD sockVersion = MAKEWORD(minorVer, majorVer);
        if(::WSAStartup(sockVersion, &wsaData) != 0)
        {
            exit(0);
        }
    }
    ~CInitSock()
    {    
        ::WSACleanup();    
    }
};


#include"../common/initsock.h"
#include<iostream>
using namespace std;

CInitSock initSock;

int main()
{
	SOCKET s = ::socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP);
	if (s == INVALID_SOCKET)
	{
		cout << "创建socket失败!" << endl;
		return 0;
	}
	sockaddr_in address;
	address.sin_family = AF_INET;
	address.sin_port = htons(5678);
	address.sin_addr.S_un.S_addr = INADDR_ANY;

	if (::bind(s, (LPSOCKADDR)&address, sizeof(address)) == SOCKET_ERROR)
	{
		cout << "绑定套接字失败!" << endl;
		return 0;
	}
	cout << "socket绑定成功,等待客户端连接..." << endl;
	char receivedData[1024];
	sockaddr_in temp;
	int len = sizeof(temp);
	while (true)
	{
		int index = ::recvfrom(s, receivedData, 1024, 0, (sockaddr*)&temp, &len);
		if (index > 0)
		{
			receivedData[index] = '';
			printf("服务器端接收来自IP为:%s的数据:  %s 
", ::inet_ntoa(temp.sin_addr), receivedData);
		}
	}
	::closesocket(s);
	return 0;
}

部分函数详解:

recvfrom()

本函数用于从(已连接)套接口上接收数据,并捕获数据发送源的地址。

函数原型:

int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,  struct sockaddr FAR* from, int FAR* fromlen);

s:标识一个已连接套接口的描述字。

buf:接收数据缓冲区

len:缓冲区长度。

flags:调用操作方式。

from:(可选)指针,指向装有源地址的缓冲区。

fromlen:(可选)指针,指向from缓冲区长度值。

返回值:

若无错误发生,recvfrom()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码

原文地址:https://www.cnblogs.com/Romantic-Chopin/p/12451010.html