winsock编程基础

来源:互联网 发布:linux移动文件权限不够 编辑:程序博客网 时间:2024/05/20 16:09

今天复习了一下计算机网络的知识,就动手写了一下最简单的winsock的程序,还是有不少收获。

程序的注释中有详细的介绍各函数的功能和用法,相信对刚入门的童鞋会有帮助。

具体程序见下,服务器端:

// server.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "Winsock2.h"//#pragma comment (lib,"ws2_32.lib");int _tmain(int argc, _TCHAR* argv[]){//这个结构被用来存储被WSAStartup函数调用后返回的Windows Sockets数据WSADATA wsaData;   WORD    wVersionRequested;  int     err,n;char    buff[512]={0};//MAKEWORD是将两个byte型合并成一个word型,一个在高8位,一个在低8位wVersionRequested=MAKEWORD(2,2);//为了在应用程序当中调用任何一个Winsock API函数,首先第一件事情就是必须通过WSAStartup函数完成对Winsock服务的初始化,因此需要调用WSAStartup函数//wVersionRequested:一个WORD(双字节)型数值,指定了应用程序需要使用的Winsock规范的最高版本。//wsaDATA:            指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节err=WSAStartup(wVersionRequested,&wsaData);if(err!=0)return 0;//int socket(int domain, int type, int protocol);//socket函数对应于普通文件的打开操作(类似于fopen函数)。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符,它唯一标识一个socket。//这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。//domain:  即协议域,又称为协议族(family)//type:     指定socket类型//protocol:指定协议SOCKET sock=socket(AF_INET,SOCK_STREAM,0);//sin_family指代协议族,在socket编程中只能是AF_INET//sin_port存储端口号(使用网络字节顺序)//sin_addr存储IP地址,使用in_addr这个数据结构//htonl将一个32位数从主机字节顺序转换成网络字节顺序//htons将机器上的整数转换成“网络字节序”,网络字节序是 big-endian,也就是整数的高位字节存放在内存的低地址处。 //而我们常用的 x86 CPU (intel, AMD) 电脑是 little-endian,也就是整数的低位字节放在内存的低字节处。SOCKADDR_IN address;address.sin_addr.S_un.S_addr=htonl(INADDR_ANY);address.sin_family=AF_INET;address.sin_port=htons(6000);//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);//bind()函数把一个地址族中的特定地址赋给socket//sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket//addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址//addrlen:对应的是地址的长度bind(sock,(SOCKADDR*)&address,sizeof(SOCKADDR));//如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。//listen函数的第一个参数即为要监听的socket描述字//第二个参数为相应socket可以排队的最大连接个数//socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。listen(sock,5);printf("Waiting for client's request......\n");SOCKADDR_IN addrClient;int len=sizeof(SOCKADDR);while(1){//accept函数的第一个参数为服务器的socket描述字//第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址//第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接SOCKET conn=accept(sock,(SOCKADDR*)&addrClient,&len);n = recv(conn,buff,512,0);buff[n]='\0';printf("recv msg from client: %s\n", buff);if(strcmp(buff,"close connect")==0){closesocket(conn);break;}}closesocket(sock);return 0;}
客户端:

// client.cpp : 定义控制台应用程序的入口点。////#pragma comment "ws2_32.lib"#include "stdafx.h"#include "Winsock2.h"int _tmain(int argc, _TCHAR* argv[]){WSADATA wsaData;   WORD    wVersionRequested;  int     err,n;char    buff[512];wVersionRequested=MAKEWORD(2,2);err=WSAStartup(wVersionRequested,&wsaData);if(err!=0)return 0;SOCKET clientSock=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN address;address.sin_addr.S_un.S_addr=inet_addr("162.105.247.166");address.sin_family=AF_INET;address.sin_port=htons(6000);connect(clientSock,(SOCKADDR*)&address,sizeof(address));char recvBuf[100];send(clientSock,"close connect",strlen("close connect"),0); closesocket(clientSock);WSACleanup();return 0;}
大家单步调试会发现,如果client端进程没有开启,那么server端就会一直停留在accept()函数处,直到client端运行到connect()函数,二者之间才建立连接。

把程序改改,然后让朋友们都装个VS,把client的代码发给他们,咱以后就在console下聊天了,直接把企鹅卸载了,哈哈哈~~~

原创粉丝点击