首页 > 代码库 > Socket 学习之 WIN32-API(1):简单通信

Socket 学习之 WIN32-API(1):简单通信

客户端程序如下:

//Client.cpp

#include <stdio.h>
#include <winsock2.h>
#include <time.h>
#include <conio.h> 

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

int main(void)
{
	WSADATA wsa;	
	/*struct WSAData
	{
		WORD wVersion;
		WORD wHighVersion;
		char szDescription[WSADESCRIPTION_LEN+1];
		char szSystemStatus[WSASYSSTATUS_LEN+1];
		unsigned short iMaxSockets;
		unsigned short iMaxUdpDg;
		char FAR * lpVendorInfo;
	};
	WSADATA结构被用来保存AfxSocketInit函数返回的WindowsSockets初始化信息*/

	WSAStartup(MAKEWORD(2,2),&wsa);
	//WORD MAKEWORD(BYTE,BYTE ) 返回版本号,WSADATA 的前两个参数
	//WSA(Windows Sockets Asynchronous,Windows异步套接字)的启动命令

	SOCKET mySocket;
	mySocket = socket(AF_INET,SOCK_DGRAM,0);
	//SOCKET  WSAAPI  socket(IN int af,IN int type,IN int protocol);
	//AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合
	//流式Socket(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。
	//数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用
	//参数3,常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC
	//为0时,会自动选择第二个参数类型对应的默认协议

	struct sockaddr_in addr;
	/*structsockaddr_in
	{	 
		short sin_family;//*Addressfamily一般来说AF_INET(地址族)PF_INET(协议族)		 
		unsigned short sin_port;/*Portnumber(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字)		 
		struct in_addr sin_addr;//*Internetaddress		 
		unsigned char sin_zero[8];//*Samesizeasstructsockaddr没有实际意义,只是为了跟SOCKADDR结构在内存中对齐		 
	};*/
	
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("172.16.70.80");
	//将一个点分十进制的IP转换成一个长整数型数(u_long类型)

	addr.sin_port = htons(8000);
	//将一个无符号短整型的主机数值转换为网络字节顺序,即大尾顺序(big-endian)

	int len  = sizeof(addr);

	while(1)
	{
		printf("请输入一段字符串用户测试延迟:");
		char buff[1024] = "\0";
		scanf("%s",buff);
		
        LARGE_INTEGER t1,t2,feq;
		/*struct union LARGE_INTEGER
		{
			DWORD LowPart;
			LONG HighPart;
		};
		64位有符号整数*/
			
		QueryPerformanceFrequency(&feq);//每秒跳动次数 
		//BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
		//返回值:非零,硬件支持高精度计数器;零,硬件不支持,读取失败。

		if(sendto(mySocket,buff,sizeof(buff),0,(struct sockaddr *)&addr,len) == SOCKET_ERROR) 
		{
			printf("发送错误!!!");
		}
		//sendto()适用于发送未建立连接的UDP数据报 (参数为SOCK_DGRAM)
		/*int PASCAL FAR sendto (
				IN SOCKET s,
				IN const char FAR * buf,
				IN int len,
				IN int flags,
				IN const struct sockaddr FAR *to,
				IN int tolen);*/

		QueryPerformanceCounter(&t1);//测前跳动次数
		//在定时前应该先调用QueryPerformanceFrequency()函数获得机器内部计时器的时钟频率。
		//接着在需要严格计时的事件发生前和发生之后分别调用QueryPerformanceCounter(),
		//利用两次获得的计数之差和时钟频率,就可以计算出事件经历的精确时间

		if(recvfrom(mySocket,buff,sizeof(buff),0,(struct sockaddr*)&addr,&len) == SOCKET_ERROR) 
		{
			printf("接受错误!!!");
		}
		//ssize_t recvfrom(int sockfd,void *buf,int len,unsigned int flags, struct sockaddr *from,socket_t *fromlen); 
		//ssize_t 相当于 int,socket_t 相当于int ,这里用这个名字为的是提高代码的自说明性。
		//buf:接收数据缓冲区
		//from:(可选)指针,指向装有源地址的缓冲区
		//fromlen:(可选)指针,指向from缓冲区长度值。

		QueryPerformanceCounter(&t2);//测后跳动次数
		//t2.LowPart //low 8 bit
		//t2.QuadPart //64 bit bunber
		
		printf("从服务端返回:%s\n",buff);
		printf("--->>时间延迟:%f秒\n",((double)t2.QuadPart-(double)t1.QuadPart)/((double)feq.QuadPart));

	}
    
	closesocket(mySocket);
	WSACleanup();
	return 0;
	getch();
}

服务器程序如下:

//Server.cpp

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

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

int main(void)
{
	WSADATA wsa;
	WSAStartup(MAKEWORD(2,2),&wsa);
	//windows Sockets Asynchronous start up

	struct sockaddr_in addr_server;
	addr_server.sin_family = AF_INET;
	addr_server.sin_port = htons(8000);
	addr_server.sin_addr.s_addr = INADDR_ANY;

	SOCKET serversocket = socket(AF_INET,SOCK_DGRAM,0);
	bind(serversocket,(struct sockaddr*)&addr_server,sizeof(addr_server));
	//int bind(int sockfd, struct sockaddr * my_addr, int addrlen);
	//用来设置给参数sockfd 的socket 一个名称. 此名称由参数my_addr 指向一sockaddr 结构,
	//对于不同的socket domain 定义了一个通用的数据结构
	
	struct sockaddr_in addr_from;
	int  fromlen = sizeof(addr_from);
	
	while(1)
	{
		char frombuff[1024] = "\0";
		printf("等待客户端输入信息!");
		if(recvfrom(serversocket,frombuff,sizeof(frombuff),0,(struct sockaddr*)&addr_from,&fromlen) == SOCKET_ERROR)
		{
			printf("服务端接受有错误!!");
		}
		printf("客户端输入的是:%s\n",frombuff);
                //Sleep(5000);
		if(sendto(serversocket,frombuff,sizeof(frombuff),0,(struct sockaddr*)&addr_from,fromlen) == SOCKET_ERROR)
		{
			printf("服务端发送错误!!");
		}
	}

	closesocket(serversocket);
	WSACleanup();
	return 0;
	getch();
}


Socket 学习之 WIN32-API(1):简单通信