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();
}
时间: 2024-10-03 14:00:49

Socket 学习之 WIN32-API(1):简单通信的相关文章

重温WIN32 API ------ 最简单的Windows窗口封装类

1 开发语言抉择 1.1 关于开发Win32 程序的语言选择 C还是C++ 在决定抛弃MFC,而使用纯Win32 API 开发Window桌面程序之后,还存在一个语言的选择,这就是是否使用C++.C++作为C的超集,能实现所有C能实现的功能.其实反之亦然,C本身也能完成C++超出的那部分功能,只是可能需要更多行的代码.就本人理解而言, 对于巨大型项目,还是使用纯C来架构更加稳妥: 对于中小型项目来说,C++可能更方便快捷.由于目前做的是中小项目,所以决定把C++作为主要开发语言. 1.2 关于C

利用win32 api实现进程通信---通过剪切板

// c#中win32 api的调用 //windows 消息机制的原理 //clipboard viewer chain. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.I

使用win32 API 实现串口通信 (二)

通常对于串口通信协议规定,有命令帧与应答帧. 1.协议规定,如头+命令字+数据块长度+数据块+校验. 对于协议规定的具体帧,可以为每一个帧,建立一个结构体数据,用于存储我将要接收的数据,这样我们可以事先建立多个结构体,通常大概会建立10到50不等,这与通信的数据协议有关. 2.现在我们要考虑的是如何将一个完整的数据帧去掉头.命令字.校验,存入结构体中,以便我们可以直接使用结构体中数据成员,也方便使用.通常C++的做法是使用运算符重载进行复制,将一个我们接收到buffer数据帧,复制到结构体中.

Win32 API编程——前言

一丶什么是Win32 API? 简单来说,就是微软为了保护操作系统的安全稳定,不允许运行在用户层的进程随意操控系统内核,而是必须按照一定方式.就是说我们用户层要与系统内核层交互(比如对内存.进程操作),只能通过调用Windows内核层提供的接口函数,也就是Win32API来操控.这些API以DLL(动态链接库)的形式保存(一般在SYSTEM32文件夹中,你可以发现大量的DLL),我们最常用的是kernel32.dll.user32.dll和gdi32.dll. 所有基于NT内核(包括XP到Win

Win32 API 之 socket网络编程

对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清,只知其所以而不知起所以然.         同步方式指的是发送方不等接收方响应,便接着发下个数据包的通信方式:而异步指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式.        阻塞套接字是指执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上,比如调用recv(

【转】Qt Socket简单通信

最近要用到Qt的Socket部分,网上关于这部分的资料都比较复杂,我在这总结一下,把Socket的主要部分提取出来,实现TCP和UDP的简单通信. 1.UDP通信 UDP没有特定的server端和client端,简单来说就是向特定的ip发送报文,因此我把它分为发送端和接收端. 注意:在.pro文件中要添加QT += network,否则无法使用Qt的网络功能. 1.1.UDP发送端 #include <QtNetwork> QUdpSocket *sender; sender = new QU

C#调用Win32 api学习总结

从.NET平台调用Win32 API Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制Windows的接口. 一.    基础知识 Win32 API是C语言(注意,不是C++语言,尽管C语言是C++语言的子集)函数集. 1. Win32 API函数放在哪里? Win32 API函数是Windows的核心,比如我们看到的窗体.按钮.对话框什么的,都是依靠Win32函

C++ Socket 学习笔记

Socket学习笔记 以下均为整理,做参考之用. IP Address IP地址是指互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),是IP Address的缩写.IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异. IP地址被用来给Internet上的电脑一个编号.大家日常见到的情况是每台联网的PC上都需要有IP地址,才能正常通信.我们可以把"个人电脑"比作"

socket学习及各类错误码(部分转)

如果本地有多个网卡(即多个ip),要指定本地发送网卡,则在建立的socket上bind所指定的网卡进行connect和send操作.例子程序如下: #include <stdio.h>#include "WinSock2.h"#pragma comment(lib,"ws2_32.lib") SOCKET tcp_socket;SOCKADDR_IN tcpAddr;const int BufLen=1024;char SendBuf[BufLen];