Winsocket编程一般步骤-服务端编程
来源:互联网 发布:windows系统是什么 编辑:程序博客网 时间:2024/05/21 10:30
Socket编程是网络编程的重要组成部分,编写简单的服务端程的程序的一般的步骤如下
第一步:包含WinSocket的头文件和动态链接库(DLL)
#include <Winsock2.h>#include <windows.h>#pragma comment(lib,"ws2_32")
第二步:初始化WSAStartup 在MSDN中WSAStarup的原型如下:
int WSAStartup( __in WORD wVersionRequested, __out LPWSADATA lpWSAData);
其中的第一个参数是版本,第二个参数是一个指向WSADATA结构体的指针,代码如下:
WORD Version = MAKEWORD(2,2); //通过MAKEWORD来设定版本,高版本和低版本都为2,也就是限定了版本必须为2WSADATA wsadata ; //结构体的一个成员 wsadata//初始化并判断是不是成功,如果成功的话返回的是0,不成功的话返回的值为非0,那么就要使用WSAleanup()函数了if(WSAStartup(Version,&wsadata)){cout<<"WSAStartup Error!"<<endl;WSACleanup();}
第三部,初始化一个Socket,
在MSDN中socket的原型如下
SOCKET WSAAPI socket( __in int af, __in int type, __in int protocol);
其中第一个参数为网络层协议类型,第二个参数为socket类型,第三个参数为传输层的协议类型,代码如下:
//第一个参数多数时候为AF_INET,第二个参数可以为SOCK_STREAM适用于可信连接,也就是tcp链接,或者为SOCK_DGRAM,适用于UDP协议第三个参数为传输层协议,如果第二个参数为SOCK_STREAM,这里就为IPPROTO_TCP,如果是SOCK_DGRAM,这里就为IPPROTO_UDPSOCKET ServerSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(ServerSocket ==INVALID_SOCKET){cout<<"Socket Fail"<<endl;}
第四步:bind
在MSDN中bind的定义如下:
int bind( __in SOCKET s, __in const struct sockaddr* name, __in int namelen);
第一个参数一个已经初始化的socket,第二个参数为执行sockaddr或者是sockaddr_in的结构体的起始地址,
第三个参数为结构体的大小,代码如下:
sockaddr_in ServerAddr;//定义一个结构体成员,这里使用的是sockaddr_in结构体ServerAddr.sin_family=AF_INET;//初始化成员的sin_family为AF_INETServerAddr.sin_addr.S_un.S_addr=INADDR_ANY;//允许任意的IP地址进行连接ServerAddr.sin_port=htons(2012);//侦听端口为2012,这里使用了htons函数//这里需要说明的是需要对第二个参数进行强制类型转换,(LPSOCKADDR)&ServerAddr,并且判断是不是bind成功,成功后返回的是为0if(bind(ServerSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))){cout<<"bind Fail"<<endl;}
第五步:侦听
在MSDN中listen的原型如下:
int listen( __in SOCKET s, __in int backlog);
依然第一个参数为初始化了的socket,第二个参数为最大允许的连接数,代码如下:
//这里依然使用的是上面的socket:ServerSocketif(listen(ServerSocket,5)){cout<<"listen Fail"<<endl;}
第六步:accept
在MSDN中原型如下:
SOCKET accept( __in SOCKET s, __out struct sockaddr* addr, __inout int* addrlen);
第一个参数一个新的客户端的Socket,这里需要定义一个,第二个参数依然为执行sockaddr或者是sockaddr_in的结构体的首地址,第三个参数为长度,这里accept负责对新定义的socket进行初始化,如果成功accept返回的一个可用的sokcet。
代码如下:
sockaddr_in Clientaddr;//定义一个结构体成员SOCKET ClientSocket;//定义一个socket用于接收accept的返回值int lAddrlen=sizeof(Clientaddr);//获取结构体的长度while(TRUE){//因为要一直的侦听,所以这里使用无限循环ClientSocket=accept(ServerSocket,(LPSOCKADDR)&Clientaddr,&lAddrlen);//与上面类似,需要强制转换,第一个参数为已经初始化的socketif(ClientSocket==INVALID_SOCKET){cout<<"accept Fail"<<endl;}else{cout<<"接受到一个信息"<<endl;}
第七步:如果accept成功,recv消息
在MSDN中recv原型如下:
int recv( __in SOCKET s, __out char* buf, __in int len, __in int flags);
第一个参数为accept返回的socket,第二个参数为输出接收的消息的一个指针,第三个为消息的长度,第四个为标志,设定接收数据的方式,代码如下:
char RecvMessage[1024]; //判断是不是成功接收,成功接收返回的是接收的数据的长度,if(recv(ClientSocket,RecvMessage,1024,0){cout<<"recv Message Fail"<<endl;}
第八步:(可选):回复客户端消息 send
send在MSDN中的代码如下:
int send( __in SOCKET s, __in const char* buf, __in int len, __in int flags);
第一个参数为accept返回的socket,第二个参数为内容的开始地址,第三个为长度,第四个为发送的方式,代码如下:
char * Message ="HellO Client!"; //判断是不是成功发送,成功发送返回的是发送的字节数,if(send(ClientSocket,Message,strlen(Message),0){cout<<"send Message Fail"<<endl;}
第九步:完成后,关闭客户端与服务端的socket:
closesocket(ClientSocket);}//上面while的结束部分
第十步:“清理”现场:
closesocket(ServerSocket);WSACleanup();return 0;
总结下,代码如下:
#include <iostream>#include <Winsock.h>#pragma comment(lib,"ws2_32")using namespace std;int main(int argc,char argv[]){WORD Version = MAKEWORD(2,2);WSADATA wsadata ;if(WSAStartup(Version,&wsadata)){cout<<"WSAStartup Error!"<<endl;WSACleanup();}SOCKET ServerSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(ServerSocket ==INVALID_SOCKET){cout<<"Socket Fail"<<endl;}sockaddr_in ServerAddr;ServerAddr.sin_family=AF_INET;ServerAddr.sin_addr.S_un.S_addr=INADDR_ANY;ServerAddr.sin_port=htons(2012);if(bind(ServerSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))){cout<<"bind Fail"<<endl;}if(listen(ServerSocket,5)){cout<<"listen Fail"<<endl;}sockaddr_in Clientaddr;SOCKET ClientSocket;int lAddrlen=sizeof(Clientaddr);while(TRUE){ClientSocket=accept(ServerSocket,(LPSOCKADDR)&Clientaddr,&lAddrlen);if(ClientSocket==INVALID_SOCKET){cout<<"accept Fail"<<endl;}else{cout<<"接受到一个信息"<<endl;}char RecvMessage[1024];if(recv(ClientSocket,RecvMessage,1024,0)<0){cout<<"recv Message Fail"<<endl;}char * Message ="HellO Client!";if(send(ClientSocket,Message,strlen(Message),0)<0){cout<<"send Message Fail"<<endl;}closesocket(ClientSocket);}closesocket(ServerSocket);WSACleanup();return 0;}
转自:http://kuaile.in/archives/311
Winsocket编程一般步骤-客户端编程
前面的文章有详细的介绍过服务端的编程,在客户端的代码的实现相对于服务端的代码要简单些,客户端可以通过IP地址直接连接,也可以通过静态域名或者是3322动态域名来连接服务器,下面是具体的代码的实现
第一步 包含头文件和DLL
123#include <winsock.h>
#include <iostream>
#pragma comment(lib,"ws2_32")
第二步 初始化WSAStartup
12345WORD
wVersion = MAKEWORD(2,2);
WSADATA ClientData;
if
(WSAStartup(wVersion,&ClientData)){
cout<<
"WSAStartup Fail"
<<endl;
}
第三步 (可选):针对于使用静态域名或者是3322等动态域名进行连接,需要对域名进行DNS解析获得对应的IP地址,如果使用的是ip地址进行连接的话,直接跳到第四步123456789//通过gethostbyname来获取域名的数字IP地址,gethostbyname返回的是hostent结构体指针
hostent * RemoteAddr;
RemoteAddr=gethostbyname(
"kuaile.in"
);
/*通过inet_ntoa将数字地址转换为ascii形式,也就是类似于xxx.xxx.xxx.xxx形式
由于gethostbyname返回的数字地址保存在h_addr_list数组中,这里去第一个数字地址来转换 由MSDN可知,inet_ntoa的参数为 An in_addr structure that represents an Internet host address ,
那么需要强制转换地址为结构体指针的形式,然后取地址
inet_ntoa返回的是字符串数组,通过定义一个字符串指针来接受ASCII形式的IP地址的首地址*/
char
* IP;
IP=inet_ntoa(*(
struct
in_addr *)RemoteAddr->h_addr_list[0]);
第四步 connect 连接服务器
1234567891011sockaddr_in Clientaddr;
Clientaddr.sin_port = htons(2012);
Clientaddr.sin_addr.S_un.S_addr = inet_addr(IP);
//inet_addr(),参数为一个字符串,将IP字符串的地址传递给inet_addr
Clientaddr.sin_family =AF_INET;
if
(connect(ClientSocket,(LPSOCKADDR)&Clientaddr,
sizeof
(Clientaddr))){
cout<<
"connect Fail"
<<endl;
//如果连接失败,释放资源
closesocket(ClientSocket);
WSACleanup();
return
0;
}
第五步 send 发送消息
1234567char
* buff =
"Hello Server!"
;
if
(send(ClientSocket,buff,
strlen
(buff),0)<0){
cout<<
"send Fail"
<<endl;
}
else
{
cout<<
"send Success"
<<endl;
}
第六步 recv 接收消息
123456789101112char
RecMessage[1024];
int
MessageLen=recv(ClientSocket,RecMessage,1024,0);
if
(MessageLen<0){
cout<<
"recv Fail"
<<endl;
}
else
{
/*通过recv获取的长度为MessageLen,那么将数组的地MessageLen的值置为‘\0’,也就是给
字符串数组加上一个结束符,那么cout遇到结束符就能停止输出了,免去了使用for循环,提高了
程序的执行效率*/
RecMessage[MessageLen]=0x00;
cout<<RecMessge<<endl;
}
第七步 释放资源
12closesocket(ClientSocket);
WSACleanup();
1/*备注:如果想要实现连接上了服务器后与服务器进行不间断的交流的话,只需要将send和recv重写为两个函数,通过向函数传递socket来实现简单的交流的目的*/
完整的代码如下:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061#include <windows.h>
#include <Winsock.h>
#include <iostream>
#pragma comment(lib,"ws2_32")
using
namespace
std;
int
main(
int
argc,
char
argv[])
{
WORD
wVersion = MAKEWORD(2,2);
WSADATA ClientData;
if
(WSAStartup(wVersion,&ClientData)){
cout<<
"WSAStartup Fail"
<<endl;
}
SOCKET ClientSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if
(ClientSocket==INVALID_SOCKET){
cout<<
"socket Fail"
<<endl;
}
//通过gethostbyname来获取域名的数字IP地址,gethostbyname返回的是hostent结构体指针
hostent * RemoteAddr;
RemoteAddr=gethostbyname(
"kuaile.in"
);
//通过inet_ntoa将数字地址转换为ascii形式,也就是类似于xxx.xxx.xxx.xxx形式
//由于gethostbyname返回的数字地址保存在h_addr_list数组中,这里去第一个数字地址来转换
//由MSDN可知,inet_ntoa的参数为 An in_addr structure that represents an Internet host address ,
//那么需要强制转换地址为结构体指针的形式,然后取地址
//inet_ntoa返回的是字符串数组,通过定义一个字符串来接受ASCII形式的IP地址
char
* IP;
IP=inet_ntoa(*(
struct
in_addr *)RemoteAddr->h_addr_list[0]);
sockaddr_in Clientaddr;
Clientaddr.sin_port = htons(2012);
Clientaddr.sin_addr.S_un.S_addr = inet_addr(IP);
//inet_addr(),参数为一个字符串,将IP字符串的值传递给inet_addr
Clientaddr.sin_family =AF_INET;
if
(connect(ClientSocket,(LPSOCKADDR)&Clientaddr,
sizeof
(Clientaddr))){
cout<<
"connect Fail"
<<endl;
closesocket(ClientSocket);
WSACleanup();
return
0;
}
char
* buff =
"Hello Server!"
;
if
(send(ClientSocket,buff,
strlen
(buff),0)<0){
cout<<
"send Fail"
<<endl;
}
else
{
cout<<
"send Success"
<<endl;
}
char
RecMessage[1024];
int
MessageLen=recv(ClientSocket,RecMessage,1024,0);
if
(MessageLen<0){
cout<<
"recv Fail"
<<endl;
}
else
{
RecMessage[MessageLen]= 0X00;
cout<<RecMessage<<endl;
}
closesocket(ClientSocket);
WSACleanup();
return
0;
}
- Winsocket编程一般步骤-服务端编程
- winsocket 编程
- winsocket编程
- WinSocket编程
- Winsocket编程
- C#网络编程之客户端编程与服务端的一般步骤(8)
- 【WinSocket】WinSocket 编程入门【精华】
- 网络编程的一般步骤
- 网络编程的一般步骤
- Delphi4的Winsocket编程
- winsocket编程实例
- winsocket编程实例
- 一个WinSocket编程实例
- WinSocket编程详解
- MFC WinSocket编程
- WinSocket简单编程实验
- WinSocket简单编程实验
- 网络-WinSocket-socket编程
- 只用getchar函数读入一个整数(算法竞赛入门经典 完整版)
- 谈谈iOS中粘性动画以及果冻效果的实现
- 第六章
- 2015062202 - CSDN手机app
- 友元类——计算两点间的距离
- Winsocket编程一般步骤-服务端编程
- 如何使用laravel搭建后台登录系统
- Collection接口
- leetcode-141-Linked List Cycle
- 分治法进行排序
- web python -- WSGI接口
- CDOJ 1059 秋实大哥与小朋友(离散化)
- 今日总结
- 基于深层神经网络的命名实体识别技术