Windows网络编程
2017-01-14 20:53
309 查看
1.先总结一些会用到的知识
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;
}
这些是最基础,最简单的编程,实际应用中要更加复杂,慢慢总结。
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;
}
这些是最基础,最简单的编程,实际应用中要更加复杂,慢慢总结。
相关文章推荐
- windows网络编程
- 《windows网络编程》--->套接字(I/O)模式 介绍及其选择
- windows网络编程(第2版)读书笔记
- Windows网络编程(TCP/UDP)
- Windows网络编程
- Windows网络编程
- windows网络编程(二)——传送图片
- windows网络编程经典入门
- Windows网络编程(第2版)中遇到的一些问题
- Windows网络编程 の 原始套接字学习笔记ICMP
- windows网络编程头文件注意事项
- Windows网络编程系列教程之四:Select模型
- Windows网络编程
- Windows网络编程
- windows网络编程(三)——UDP
- [转][推荐]windows网络编程经典入门
- 发送udp包-windows网络编程
- Windows网络编程 — UDP完成端口的实现
- Windows网络编程附书代码(简单的服务器与客户端)
- windows网络编程(1)同步套接字