网络字节顺序:
网络中传输的数据使用的均是大尾方式, 大尾方式是 高位存放低字节,地位存放高字节。
windows提供了一些函数来处理本地机器的字节顺序和网络字节顺序的转换:
u_short htons(u_short hostshort); u_long htonl(u_long hostlong); u_short ntohs(u_short netshort); u_long ntohl(u_long netlong);
这些API是平台无关的,使用它们可以正确运行在所有机器上
网络编程基础:
每个使用Winsock进行网络开发的Windows应用程序都必须包含Winsock2.h,另外还需要一个静态库ws2_32.lib。在使用它们的时候需要对这个库进行一次初始化,使用完后要对该库进行释放。
1.初始化ws2_32.dll 动态链接库的函数: WSAStartup()
2.释放ws2_32.dll的函数: WSACleanup()
3.加载ws2_32.lib : #pragma comment (lib, "ws2_32") //指明要链接到ws2_32.lib 库
.dll 文件就是动态链接库,.lib 文件是提供程序开发用的导入库, .h文件包含了导出函数的声明
一个简单的通信例子:
服务器端:
//#include <Windows.h> //不要加进来!!!
#include <iostream>
#include <string.h>
#include <WinSock2.h> //winsock2.h 和 windows.h的顺序不要反
#include <Windows.h>
#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "winmm.lib") //用于支持 mci device
using namespace std;
//帮助命令宏
#define HELPMSG "help - Show Help Menu \r\n"\
"getsysinfo - Get SysTem Information \r\n"\
"open - Open The CDRom \r\n"\
"close - Close The CDRom \r\n"\
"swap - Swap Mouse Button \r\n"\
"restore - Restore Mouse Button \r\n"\
"exit - Quit BdShell"
#define NAME_LEN 20
//保存获取的系统信息
typedef struct _SYS_INFO
{
OSVERSIONINFO OsVer; //保存操作系统的信息
char szComputerName[NAME_LEN]; //保存计算机名称
char szUserName[NAME_LEN]; //保存当前登录名称
}SYS_INFO, *PSYS_INFO;
//函数声明
BOOL Dispatch(SOCKET, char *); //分发命令
void GetSysInfo(SYS_INFO *); //获得系统信息
void SetCdaudio(BOOL); //打开或者关闭光驱
void SetMouseButton(BOOL); //交换或者恢复鼠标左右键功能
int main()
{
WSADATA wsaData; //保存DLL库的详细信息
::WSAStartup(MAKEWORD(2,2), &wsaData);
//创建套接字
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in sockaddr;
sockaddr.sin_family = PF_INET; //地址家族 PF_INET指互联网地址家族(TCP/IP)
//如果IP地址为 INADDR_ANY 系统会自动使用当前主机配置的所有IP地址
sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //IP地址
sockaddr.sin_port = htons(8008); //端口号
//绑定套接字到指定的IP地址和端口号
::bind(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR));
//进入监听模式
::listen(s, 1); //1 表示监听队列中允许保持的尚未处理的最大连接数量
//保存客户端的信息
sockaddr_in clientAddr;
int nSize = sizeof(SOCKADDR);
//用于取的对方的地址信息
SOCKET clientSock;
printf("服务器已启动...\n");
//接受连接请求
clientSock = ::accept(s, (SOCKADDR*)&clientAddr, &nSize);
while(TRUE)
{
//发送一个命令提示
::send(clientSock, "BdShell>", strlen("BdShell>") + sizeof(char), 0);
char buff[MAXBYTE] = {0};
//接收客户端发来的命令
::recv(clientSock, buff, MAXBYTE, 0);
if(!strcmp(buff, "exit"))
break;
//分发命令
BOOL bRet = Dispatch(clientSock, buff);
if(bRet == FALSE)
{
::send(clientSock, "Commend Unsuccessfully",
strlen("Commend Unsuccessfully") + sizeof(char), 0);
printf("next->\n");
}
else
{
::send(clientSock, "Commend successfully",
strlen("Comment successfully") + sizeof(char), 0);
printf("next->\n");
}
}
closesocket(clientSock);
closesocket(s);
WSACleanup();
return 0;
}
BOOL Dispatch(SOCKET sock, char * szCmd)
{
BOOL bRet = FALSE;
//根据不同的命令,完成不同的功能
if(!strcmp(szCmd, "help"))
{
//
::send(sock, HELPMSG, strlen(HELPMSG) + sizeof(char), 0);
bRet = TRUE;
}
//获取系统信息
else if(!strcmp(szCmd, "getsysinfo"))
{
//
SYS_INFO sysInfo = {0};
GetSysInfo(&sysInfo);
printf("%s\n", (char *)sysInfo.OsVer.szCSDVersion);
printf("%s\n", sysInfo.szComputerName);
printf("%s\n", sysInfo.szUserName);
::send(sock, (const char *)&sysInfo, sizeof(SYS_INFO), 0);
bRet = TRUE;
}
//打开光驱
else if(!strcmp(szCmd, "open"))
{
//
SetCdaudio(TRUE);
bRet = TRUE;
}
//关闭光驱
else if(!strcmp(szCmd, "close"))
{
//
SetCdaudio(FALSE);
bRet = TRUE;
}
//交换鼠标左右键功能
else if(!strcmp(szCmd, "swap"))
{
//
SetMouseButton(TRUE);
bRet = TRUE;
}
//回复鼠标左右键功能
else if(!strcmp(szCmd, "restore"))
{
//
SetMouseButton(FALSE);
bRet = TRUE;
}
else
{
//
::send(sock, "no this commend!",
strlen("no this commend!") + sizeof(char),0);
}
return bRet;
}
//获得系统信息
void GetSysInfo(SYS_INFO * sysInfo)
{
unsigned long nSize = MAXBYTE;
sysInfo->OsVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
//获得操作系统版本信息
::GetVersionEx(&sysInfo->OsVer);
//获得计算机名称
::GetComputerNameA(sysInfo->szComputerName, &nSize);
//获得当前登录名称
nSize = MAXBYTE;
::GetUserNameA(sysInfo->szUserName, &nSize);
}
void SetCdaudio(BOOL bOpen)
{
if(bOpen)
{
//打来光驱
::mciSendStringA("set cdaudio door open", NULL, NULL, NULL);
}
else
{
//关闭光驱
::mciSendStringA("set cdautio door closed", NULL, NULL, NULL);
}
}
void SetMouseButton(BOOL bSwap)
{
if(bSwap)
{
//交换左右键
::SwapMouseButton(TRUE);
}
else
{
//恢复
::SwapMouseButton(FALSE);
}
}
客户端:
//#include <Windows.h>
#include <WinSock2.h>
#include <stdio.h>
#include <conio.h>
#pragma comment (lib, "ws2_32")
#define NAME_LEN 20
typedef struct _SYS_INFO
{
OSVERSIONINFO OsVer;
char szComputerName[NAME_LEN];
char szUserName[NAME_LEN];
} SYS_INFO, *PSYS_INFO;
void ShowSysInfo(PSYS_INFO sysInfo)
{
if(sysInfo->OsVer.dwPlatformId == VER_PLATFORM_WIN32_NT) //平台ID
{
if(sysInfo->OsVer.dwMajorVersion == 6 && sysInfo->OsVer.dwMinorVersion ==1)
{
printf("windows 7 %s\n", sysInfo->OsVer.szCSDVersion); // 系统和补丁包
}
else
{
printf("other system\n");
}
}
printf("computer name is: %s \n", sysInfo->szComputerName);
printf("user name is: %s \n", sysInfo->szUserName);
}
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//服务器端信息
sockaddr_in serverAddr;
serverAddr.sin_family = PF_INET;
serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
serverAddr.sin_port = htons(8008);
//连接服务器端
if(connect(clientSock, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR)) == -1)
{
printf("连接失败!");
}
printf("客户端已启动...\n");
while(TRUE)
{
char buff[MAXBYTE] = {0};
char cmd[MAXBYTE] = {0};
//接收信息
recv(clientSock, buff, MAXBYTE, 0);
printf("%s", buff);
//输入命令
scanf("%s", cmd);
//发送命令
send(clientSock, cmd, MAXBYTE, 0);
if( !strcmp(cmd, "exit"))
{
printf("login out! \r\n");
break;
}
memset(buff, 0, MAXBYTE);
recv(clientSock, buff, MAXBYTE, 0);
if( !strcmp(cmd, "getsysinfo"))
{
PSYS_INFO sysInfo = (PSYS_INFO)buff;
ShowSysInfo(sysInfo);
}
else
{
printf("%s \r\n", buff);
}
}
printf("you have exited!\n");
getch();
closesocket(clientSock);
WSACleanup();
return 0;
}