您的位置:首页 > 理论基础 > 计算机网络

Windows网络编程

2017-01-14 20:53 309 查看
1.先总结一些会用到的知识

 IP地址:IPV4中计算机都分配一个地址,该地址是一个32位的数值表示;客户端和服务器通信的时候需要指定一个IP地址和端口。
      IP地址一般是用“Internet标准点分表示法” 像a.b.c.d一样指定的,每一个字母代表一个字节的数字(十进制、八进制
或十六进制)从左到右分配了一个无符号长整数的4个字节。
unsigned long inet_addr(_In_ const char *cp) :把一个点分IP地址转换成一个32位的无符号长整数。
网络字节序:TCP/IP协议中规定好的数据表示方法,顺序采用big endian排序方式;
主机字节序:主机表示数据的方法,不同的操作系统字节序不同,有big endian,有的是little endian ;若是主机字节序与网络字节序不同,则需
要转换成一致的字节序;
转换字节序用到的函数:
网络字节序——主机字节序                      主机字节序——网络字节序
                       ntohl                                     htonl
WSANtohl WSAHtonl ntohs htons
WSANtohs WSAHtonsSOCKADDR_IN结构: 用来指定IP地址和服务端口信息。 struct sockaddr_in {    short  sin_family; //    协议族   一般为AF_INET     u_short  sin_port;     //   端口号,必须使用网络字节序     struct   in_addr  sin_addr; //IP地址信息     char     sin_zero[8]; //为了使sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节 }
2.面向连接的TCP协议编程 1)服务器端程序
#include<iostream>
#include<WinSock2.h>
#include<stdio.h>

#pragma comment(lib,"Ws2_32")//添加库文件

using namespace std;

int main()
{
//1.创建套接字(socket)
WORD version =MAKEWORD(2,2);//先确定使用套接字的版本
WSADATA wdata;
int erro =WSAStartup(version,&wdata);//启动套接字
if(erro!=0)
{
cout<<"套接字启动失败!"<<endl;

}
if((LOBYTE(wdata.wVersion)!=2)||(HIBYTE(wdata.wVersion)!=2))//如果版本不对,清除当前的套接字
{
WSACleanup();
}
SOCKET sockSer=socket(AF_INET,SOCK_STREAM,0);//指定协议族、套接字类型(流式套接字)、协议初始化

//2.将套接字绑定到一个本地地址和端口上(bind)

//指定服务器IP
SOCKADDR_IN Servaddr;
Servaddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//IP
Servaddr.sin_family=AF_INET;//协议族,必须是AF_INET
Servaddr.sin_port=htons(6000);//IP端口

bind(sockSer,(sockaddr*)&Servaddr,sizeof(sockaddr));//将socket与本地的一个IP关联

//3.将套接字设置成监听模式,准备接收客户的请求(listen)
listen(sockSer,10);

//4.等待客户请求到来,当请求到来后,接收连接请求,返回一个新的对应于此次连接的套接字(accept)

SOCKADDR_IN cl
4000
ientadd;
int len = sizeof(sockaddr);

while(1)
{
Sleep(10000);
char sendbuf[100];
SOCKET sockCon =accept(sockSer,(sockaddr*)&clientadd,&len);//返回一个新的对应于此次连接的套接字,将地址和端口空出来

//5.用返回的套接字和客户端进行通信(send/recv)

sprintf(sendbuf,"This is: Server!");
send(sockCon,sendbuf,strlen(sendbuf)+1,0);//发送用连接的套接字,不能用正在监听的那个套接字

char recvbuf[100];
recv(sockCon,recvbuf,100,0);
cout<<"Server Receive :"<<recvbuf<<endl;
closesocket(sockCon);

}
cout<<"a: "<<endl;
system("pause");
return 0;

}

 
2.客户端的程序
    
#include<WinSock2.h>
#include<iostream>
 
 
#pragma comment(lib,"Ws2_32")
 
using namespace std;
 
int main()
{
//客户端
 //1.创建套接字
WSADATA wsd;
wsd.wVersion=MAKEWORD(2,2);//确定套接字的版本
int erro;
erro=WSAStartup(wsd.wVersion,&wsd);
if(erro!=0)
{
  cout<<"套接字启动失败!"<<endl;

}
if((LOBYTE(wsd.wVersion)!=2)||(HIBYTE(wsd.wVersion)!=2))
{
    cout<<"套接字版本错误!"<<endl;
WSACleanup();

}
SOCKET Clientsocket = socket(AF_INET,SOCK_STREAM,0);
 
SOCKADDR_IN  Servadd;
Servadd.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
Servadd.sin_family=AF_INET;
Servadd.sin_port=htons(6000);
 
//2.向服务器发送连接请求(connect)
connect(Clientsocket,(sockaddr*)&Servadd,sizeof(sockaddr));//套接字,服务器IP地址,地址结构体的长度
 
//3.与服务器通信(send/recv)
char sendbuf[100],recvbuf[100];
  while(1)
  {
  Sleep(10000);
     recv(Clientsocket,recvbuf,100,0);
 cout<<"receive :"<<recvbuf<<endl;
 send( Clientsocket,"this is client",strlen("this is client")+1,0);
     
 closesocket(Clientsocket);
// WSACleanup();
  
  }
 
system("pause");
return 0;
}
 

以上是使用TCP协议的简单编程,TCP是面向连接的通信,是流协议,UDP是无连接通信,几乎是基于消息的,因此在接收函数的调用必须提供一个足够大的缓冲空间,如果缓冲区不够大,接收调用会失败,出现错误WSAEMSGSIZE,缓冲区填满,未接收完的数据会丢弃。
//Udp服务器
#include<WinSock2.h>
#include<iostream>

#pragma comment(lib,"Ws2_32")
using namespace std;

int main()
{
//服务器端
//1.创建套接字
DWORD wversion;
wversion =MAKEWORD(2,2);
WSADATA wsa;
wsa.wVersion=wversion;
int erro=0;
erro= WSAStartup(wversion,&wsa);
if(erro!=0)
{
cout<<"套接字启动失败!"<<endl;
}
if((LOBYTE(wsa.wVersion)!=2)||(HIBYTE(wsa.wVersion)!=2))
{
cout<<"套接字版本错误!"<<endl;
WSACleanup();
}
SOCKET socket_uServer = socket(AF_INET,SOCK_DGRAM,0);//协议族、格式、初始化

//2.绑定套接字
SOCKADDR_IN SockAddr,sendaddr;
SockAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
SockAddr.sin_family=AF_INET;
SockAddr.sin_port=htons(7000);
int len = sizeof(sockaddr);
bind(socket_uServer,(sockaddr*)&SockAddr,len);

//3.等待数据连接
char recvbuf[100];
int sendlen= sizeof(sendaddr);
recvfrom(socket_uServer,recvbuf,100,0,(sockaddr*)&sendaddr,&sendlen);
cout<<"recv : "<<recvbuf<<endl;
cout<<"the IP is"<<inet_ntoa(sendaddr.sin_addr)<<endl;
char sendbuf[]="I received your message \0";
sendto(socket_uServer,sendbuf,strlen(sendbuf),0,(sockaddr*)&sendaddr,sizeof(sendaddr));
closesocket(socket_uServer);
WSACleanup();
system("pause");
return 0;
}UDP客户端
#include<WinSock2.h>
#include<iostream>

#pragma comment(lib,"Ws2_32")
using namespace std;

int main()
{
//服务器端
//1.创建套接字
DWORD wversion;
wversion =MAKEWORD(2,2);
WSADATA wsa;
wsa.wVersion=wversion;
int erro=0;
erro= WSAStartup(wversion,&wsa);
if(erro!=0)
{
cout<<"套接字启动失败!"<<endl;
}
if((LOBYTE(wsa.wVersion)!=2)||(HIBYTE(wsa.wVersion)!=2))
{
cout<<"套接字版本错误!"<<endl;
WSACleanup();
}
SOCKET socket_uClient = socket(AF_INET,SOCK_DGRAM,0);//协议族、格式、初始化

//2.发送数据
SOCKADDR_IN SockAddr,sendaddr;
SockAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
SockAddr.sin_family=AF_INET;
SockAddr.sin_port=htons(7000);
int len = sizeof(sockaddr);

char sendbuf[]="I received ";
sendto(socket_uClient,sendbuf,strlen(sendbuf)+1,0,(sockaddr*)&SockAddr,sizeof(SockAddr));
char recvserbuf[100];
recvfrom(socket_uClient,recvserbuf,100,0,(sockaddr*)&SockAddr,&len);
cout<<"recv from server: "<<recvserbuf<<endl;
closesocket(socket_uClient);
WSACleanup();
system("pause");
return 0;
}

这些是最基础,最简单的编程,实际应用中要更加复杂,慢慢总结。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: