当前位置: 首页 > 编程技术, 网络技术 > 正文

Winsocket编程一般步骤-客户端编程

前面的文章有详细的介绍过服务端的编程,在客户端的代码的实现相对于服务端的代码要简单些,客户端可以通过IP地址直接连接,也可以通过静态域名或者是3322动态域名来连接服务器,下面是具体的代码的实现

第一步 包含头文件和DLL

#include <winsock.h>
#include <iostream>
#pragma comment(lib,"ws2_32")

第二步 初始化WSAStartup

WORD wVersion = MAKEWORD(2,2);
WSADATA ClientData;
if(WSAStartup(wVersion,&ClientData)){
cout<<"WSAStartup Fail"<<endl;
}


第三步 (可选):针对于使用静态域名或者是3322等动态域名进行连接,需要对域名进行DNS解析获得对应的IP地址,如果使用的是ip地址进行连接的话,直接跳到第四步

//通过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 连接服务器

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;
}

第五步 send 发送消息

char * buff = "Hello Server!";
if(send(ClientSocket,buff,strlen(buff),0)<0){
	cout<<"send Fail"<<endl;
}
else{
	cout<<"send Success"<<endl;
}

第六步 recv 接收消息

char  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;
}

第七步 释放资源

closesocket(ClientSocket);
WSACleanup();
 /*备注:如果想要实现连接上了服务器后与服务器进行不间断的交流的话,只需要将send和recv重写为两个函数,通过向函数传递socket来实现简单的交流的目的*/

完整的代码如下:

#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;
}


本文固定链接: http://kuaile.in/archives/313 | 蒲公英的博客

该日志由 蒲公英 于2012年01月31日发表在 编程技术, 网络技术 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: Winsocket编程一般步骤-客户端编程 | 蒲公英的博客
关键字:

Winsocket编程一般步骤-客户端编程:等您坐沙发呢!

发表评论


You must enable javascript to see captcha here!

快捷键:Ctrl+Enter