windows核心編程之網絡編程入門篇



來源:微信公衆號「編程學習基地」
node

大端小端

大端模式指數據的高字節保存在內存的低地址編程

例如:12345( 0x3039 ) 的存儲順序是 0x30、0x39windows

小端模式指數據的高字節保存在內存的高地址服務器

例如:12345( 0x3039 ) 的存儲順序是 0x3九、0x30微信

判斷大小端

方法一:網絡

#include<stdio.h>
int main(int argc, char *argv[])
{
	int i = 0x12345678;
	char c = i;
	if (c == 0x78)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

方法二:socket

#include<stdio.h>
int main(void)
{
	int  a = 0x12345678;
	char *p = (char *)&a;
	if (0x78 == *p)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

方法三:tcp

#include<stdio.h>
typedef union NODE
{
	int i;
	char c;
}Node;
int main(int argc, char *argv[])
{
	Node node;
	node.i = 0x12345678;
	if (0x78 == node.c)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

CS模型

在這裏插入圖片描述

Socket網絡編程

WSAStartup / WSACleanup

int WSAStartup ( WORD wVersionRequested,
                LPWSADATA pWSAData );

每個WSAStartup都不準對應一個WSACleanup的調用函數

socket

int socket(int af,
           int type,
           int protocol);
  • af:AF_INETAF_INET6AF_LOCAL

WinSock只支持AF_INET學習

  • type:

SOCK_STREAMSOCK_DGRAMSOCK_RAW等等

  • protocol:

若是type爲SOCK_STREAM,使用的是tcp協議

若是type爲SOCK_DGRAM,使用的是udp協議

此時protocol能夠指定爲0

若是type爲SOCK_RAW,使用的是原始套接字,protocol能夠去自定義協議,例如ICMP等協議

sockaddr_in

struct sockaddr_in { 
   short int sin_family,		//地址家族
	unsigned short int sin_port, //端口號
    struct in_addr sin_addr,	//IP地址
    unsigned char sin_zero[8],	//空字節,設爲0
}

struct in_addr:

struct in_addr{ 
	unsigned long s_addr;
}

點分十進制轉換

inet_addr()

將一個點分十進制字符串轉化爲二進制的數

in_addr_t inet_addr(const char* cp);
  • 參數:字符串,一個點分十進制的IP地址
  • 返回值:
    若字符串有效,則將字符串轉換爲32位二進制網絡字節序的IPV4地址;不然,爲INADDR_NONE

inet_ntoa()

將二進制數轉換爲一個點分十進制字符串

char *inet_ntoa(struct in_addr);
  • 參數:in_addr是一個結構體,用來表示一個32位的IPV4地址
  • 返回值:返回點分十進制的字符串在靜態內存中的指針

端口轉化函數

TCP/IP協議統一使用網絡字節順序,即大端

u_short htons(u_short hostshurt)	//主機字節順序轉網絡字節順序
u_long htonl(u_long hostshurt)		//主機字節順序轉網絡字節順序
u_short ntohs(u_short hostshurt)	//網絡字節順序轉主機字節順序
u_long ntohl(u_long hostshurt)		//網絡字節順序轉主機字節順序

一般使用htons來進行端口轉換

bind

int bind(
	SOCKET s,						//套接字句柄
	onst struct sockaddr* name,		//本地地址
	int namelen						//地址長度
); 

listen

int listen(
	SOCKET s,		//套接字句柄
	int backlog		//監聽隊列容許保持的最大鏈接數量
);

accept

SOCKET accept(
	SOCKET s,			//套接字句柄
	struct sockaddr* addr,	//協議族瀆職
	int* addrlen			//地址長度
);

connect

int connect(
	SOCKET s,	//套接字句柄
	const struct sockaddr* name,	//協議族地址
 	int namelen						//地址長度
);

tcp服務器

#include <winsock2.h>	// 爲了使用Winsock API函數
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

// 告訴鏈接器與WS2_32庫鏈接
#pragma comment(lib,"WS2_32.lib")

int main(int argc, char* argv[])
{
	// 初始化WS2_32.dll
	WSADATA wsaData;
	WORD sockVersion = MAKEWORD(2, 2);
	WSAStartup(sockVersion, &wsaData);	//請求了一個2.2版本的socket

	// 建立套節字
	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s == INVALID_SOCKET)
	{
		printf("Failed socket() \n");
		WSACleanup();
		return 0;
	}

	// 填充sockaddr_in結構
	sockaddr_in sin;
	sin.sin_family = AF_INET;				
	sin.sin_port = htons(8888);				//8888端口
	//sin.sin_addr.S_un.S_addr = INADDR_ANY;	//本地地址 
	sin.sin_addr.S_un.S_addr = inet_addr("169.254.211.52"); //172.19.12.44

	// 綁定這個套節字到一個本地地址
	if (bind(s, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		printf("Failed bind() \n");
		WSACleanup();
		return 0;
	}

	// 進入監聽模式
	if (listen(s, 2) == SOCKET_ERROR)		//最大鏈接數爲2
	{
		printf("Failed listen()");
		WSACleanup();
		return 0;
	}
	printf("Start listen:\n");
	// 循環接受客戶的鏈接請求
	sockaddr_in remoteAddr;
	int nAddrLen = sizeof(remoteAddr);
	SOCKET client;
	char szText[] = "hello!\n";
	while (TRUE)
	{
		// 接受一個新鏈接
		client = accept(s, (SOCKADDR*)&remoteAddr, &nAddrLen);
		if (client == INVALID_SOCKET)
		{
			printf("Failed accept()");
			continue;
		}

		printf(" 接受到一個鏈接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));

		// 向客戶端發送數據
		send(client, szText, strlen(szText), 0);

		// 關閉同客戶端的鏈接
		closesocket(client);
	}

	// 關閉監聽套節字
	closesocket(s);
	// 釋放WS2_32庫
	WSACleanup();

	return 0;
}

tcp客戶端地址

#include <winsock2.h>	
#include <stdio.h>
#include <windows.h>

// 告訴鏈接器與WS2_32庫鏈接
#pragma comment(lib,"WS2_32.lib")

int main(int argc, char* argv[])
{
	// 初始化WS2_32.dll
	WSADATA wsaData;
	WORD sockVersion = MAKEWORD(2, 2);
	WSAStartup(sockVersion, &wsaData);

	// 建立套節字
	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s == INVALID_SOCKET)
	{
		printf("Failed socket() \n");
		WSACleanup();
		return 0;
	}

	// 填寫遠程地址信息
	sockaddr_in servAddr;
	servAddr.sin_family = AF_INET;
	servAddr.sin_port = htons(8888);
	// 若是你的計算機沒有聯網,直接使用本地地址127.0.0.1
	servAddr.sin_addr.S_un.S_addr = inet_addr("169.254.211.52");

	if (connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)
	{
		printf("Failed connect() \n");
		WSACleanup();
		return 0;
	}

	// 接收數據
	char buff[256];
	int nRecv = recv(s, buff, 256, 0);
	if (nRecv > 0)
	{
		buff[nRecv] = '\0';
		printf(" 接收到數據:%s", buff);
	}
    
	// 關閉套節字
	closesocket(s);
	// 釋放WS2_32庫
	WSACleanup();
	return 0;
}
相關文章
相關標籤/搜索