Winsock 网络编程

用VC实现Winsock中Server和Client 之间的通信。

Winsock中用于网络编程的几个函数功能介绍:

int WSAStartup( WORD v , (LPWSADATA) &WD )   ;		//用于初始化Winsock
void WSACleanup(  ) ;							//关闭Winsock
void closesocket( SOCKET s )	;
Winsock 的建立和撤销函数


创建套接字:API 是建立在套接字概念上的,套接字是传输层提供程序的句柄,是SOCKET类型,用socket创建套接字
SOCKET socket(int af, int type, int protocol);
其中:af表示协议族,
	 	af = AF_INET :TCP/IP地址;
	 	af = AF_UNIX :UNIX地址;
	  type表示协议的套接字类型
	  	type = SOCK_STREAM : TCP协议
		type = SOCK_DGRAM : UDP协议
	  protocol : 依赖于type参数,表示使用的协议
	  	protocol = IPPROC_TCP : TCP ;
		Protocol = IPPROC_UDP :UDP ;
		protocol = 0 : 默认; 

本地服务器的绑定,监听,接收:
struct sockaddr_in{
	short sin_family ;		//告诉Winsock使用的IP地址族 
	u_short sin_port ;		//16位端口号 , 网络字节顺序 
	struct in_addr sin_addr ;		//32位IP地址,网络字节顺序 
	char sin_zero[8] ;		//填充项,是SOCKADDR_IN结构 
}
struct in_addr {
	u_long s_addr ;			//32bit的IP地址,网络字节顺序	
	
} 
bind(SOCKET s,(SOCKADDR *)&addr , sizeof(SOCKADDR)); 
int listen(SOCKET s , int backlog); 	//backlog:表示被挂起的连接的队列的最大长度
SOCKET accept(SOCKET s, (SOCKADDR *)&addr,&sizeof(SOCKADDR)) ; 

htonl:将按主机字节顺序排序的4字节数转化为按网络字节顺序排序的4字节数。
htons:将按主机字节顺序排序的2字节数转化为按网络字节顺序排序的2字节数。
inet_addr函数把一个点分IP 地址转换成按网络字节顺序排列的32位无符号长整数

客户机端的函数设置,和服务器端的类似,也是建立一个SOCKET ,然后用一个SOCKADDR_IN结构初始化要通信的服务器的地址结构信息。这个需要注意的一点就是客户机端一般不需要bind,客户机端的bind由操作系统自行完成。 接着就是向服务器发出一个connect连接请求,为:
int connect(SOCKET s , (SOCKADDR *)&addr,sizeof(SOCKADDR)) ;

待服务器和客户机之间的连接建立之后,就可以用send().recv()函数进行通信了
//面向连接的发送接收函数 
int send(SOCKET s,const char *buf , int len , int flag) //flag一般= 0
int recv(SOCKET s, const char *buf, int len , int flag)

//面向无连接的发送和接收函数:
int recvfrom(SOCKET s,char *buf, int len, int flag,(SOCKADDR *)&addr,sizeof(SOCKADDR)) ;  //其中addr用以存放操作的另外一方的地址信息 
int sendto(SOCKET s ,char *buf, int len ,int flag, (SOCKADDR *)&addr,sizeof(SOCKADDR)) ;	//其中的addr和上面的含义一样 

以下是一个实例,实现服务器与客户机之间的通信:

服务器端代码:
/*
服务器端!
*/
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")		//添加"winsock2.h的库"
int main(){				
	WSADATA wsadata ;
	if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0){			//初始化Winsock
		printf("初始化网络协议失败\n");
		exit(1) ;
	}
	SOCKET s_socket = socket(AF_INET,SOCK_STREAM,0);	//设定为TCP/IP协议,Socket类型为流式套接字
	if(s_socket == INVALID_SOCKET){
		printf("Faile to socket!\n");
		exit(1) ;
	}
	SOCKADDR_IN A ;								//设置服务器的地址结构
	A.sin_family = AF_INET ;
	A.sin_port = htons(1234);
	A.sin_addr.S_un.S_addr = htonl(INADDR_ANY) ;	//IP地址默认生成
	bind(s_socket ,(SOCKADDR *)&A,sizeof(A));		//本地信息的绑定
	listen(s_socket,5);								//服务器进入监听状态
	printf("Server is Waiting ...\n");
	SOCKADDR_IN B ;									//accept后存放客户机的本地地址结构 
	int len = sizeof(SOCKADDR) ;
	SOCKET socket_conn = accept(s_socket,(SOCKADDR *)&B ,&len);
	if(socket_conn != INVALID_SOCKET){
			printf("正在进行通信!\n");
			while(1){										//处于一直监听状态
				char meg[80] ;
				printf("输入所要传输的消息:");
				fgets(meg,80,stdin);	inet_ntoa(B.sin_addr);	//将网络字IP装换成内存字IP
				int len = strlen(meg);
				if(meg[len-1] == '\n')	meg[len-1] = 0 ;
				send(socket_conn,meg,strlen(meg)+1,0);			//发送
				printf("已发送了%d个字符\n",strlen(meg)+1);
				if(strcmp(meg,"quit") == 0){
					printf("Server is cancelling the communication!\n");
					break ;
				}

				char rev[80] ;
				recv(socket_conn,rev,80,0);						//接收
				printf("已经接收到了%d个字符%s\n",strlen(rev)+1,rev);
				if(strcmp(rev,"quit")==0){
					printf("Client is cancelling the communication!\n");
					break ;
				}
			}
			closesocket(socket_conn) ;						//关闭客户机的套接字连接
	}
	else{
		printf("Faile to aceept!\n");
	}
	closesocket(s_socket);								//关闭服务器的套接字
	WSACleanup();										//关闭Winsock

	return 0;
}

客户机端的代码:
/*
客户端!
*/
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")				//添加包含"winsock2.h的库"
int main(){

	WSADATA wsadata ;
	if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0){			//Winsock的初始化,应用的是2.2的版本
		printf("Client 初始化失败!\n");
		exit(1) ;
	}

	SOCKET c_socket = socket(AF_INET,SOCK_STREAM,0);		//创建客户端的套接字
	//此处省略了c_socket套接字的bind()操作,由操作系统自动完成绑定
	SOCKADDR_IN A ;					//设置与之通信的服务器端的套接字的地址结构的相关属性
	A.sin_family = AF_INET ;		
	A.sin_port = htons(1234);		//端口号
	A.sin_addr.S_un.S_addr = inet_addr("222.247.149.234") ;			//服务器的IP地址,根据自行需要设置即可
	int conn = connect(c_socket,(SOCKADDR *)&A,sizeof(SOCKADDR));		//与服务器建立连接

	if(conn != WSAEADDRNOTAVAIL){
		printf("正在与服务器进行通话!\n");
		while(1){
			char rev[80] ;
			recv(c_socket,rev,80,0);							//接收信息
			printf("已经接收了%d个字符: %s\n",strlen(rev)+1,rev);
			if(strcmp(rev,"quit") == 0){
				printf("Server is Cancelling the communication!\n");
				break ;
			}

			char buf[80] ;
			fgets(buf,80,stdin);
			int len = strlen(buf) ;
			if(buf[len-1] == '\n')	buf[len-1] = 0 ;
			send(c_socket,buf,strlen(buf)+1,0);			//发送信息
			printf("已发送了%d个字符!\n",strlen(buf)+1);
			if(strcmp(buf,"quit") == 0){
				printf("Client is Cancelling the communication!\n");
				break ;
			}
		}
		printf("Communication is Done!\n");
	}
	else{
		printf("Faile to connet\n");	
		exit(1) ;
	}
	closesocket(c_socket);					//关闭客户端的套接字
	WSACleanup() ;							//终止对Winsock库的使用
	return 0;
}




你可能感兴趣的:(Winsock,网络编程)