一. 服务器端
1.加载WInSock库
因为WinSock服务是通过动态链接库WinSock DLL实现的,所以调用WinSock函数前,需要加载WinSock库启动服务。
int WSAStart( WORD wVersion, LPWSADATA lpWSAData);
wVersion 指定加载的WinSock版本号,一般使用MAKEWORD(X,Y); X指副版本号,Y指主版本号;
LPWSADATA 结构包含了加载的WinSOck库的信息,可以不用到。
返回值为0,表示成功。
例:
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
2.服务器进程创建用于监听的套接字
服务器进程总是先于客户端进程启动。
SOCKET socket(int af , int type, int protocol);
af ---- 网络地址类型,一般为AF_INET;
type ------套接字类型,SOCK_STREAM为流套接字,SOCK_DGRAM为数据报套接字;
protocol---网络协议,一般取0;
返回值SOCKET为所创建的套接字的句柄。
例:SOCKET sockSrv= socket(AF_INET, SOCK_STREAM, 0);
3.绑定套接字
int bind(SOCKET s, const struct sockaddr* name, int namelen);
s---要绑定的套接字句柄;
namelen---name的字节数;
sockaddr----一般用sockaddr_in
sockaddr_in(在netinet/in.h中定义):
struct sockaddr_in {
short int sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
unsigned char sin_zero[8]; /* Same size as struct sockaddr */
}
sin_famil-----必须为AF_INET;
sin_port------指定服务器端口;
sin_addr----IP地址,(设为INADDR_ANY,以便监听每个网络接口);
sin_zero---无需设置;
例:
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(5099); //1024以上的端口号
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
4.监听
int listen(SOCKET s, int backlog);
backlog---等待连接的最大队列长度;
5.等待请求来到
SOCKET accept(SOCKET s, struct sockaddr * addr , int * addrlen);
s---监听套接字句柄;
addr --存储客户端ip信息;
addrlen --- addr长度;
返回套接字句柄,该套接字用于和客户端连接。
accept函数无连接请求是阻塞,有请求才处理。
6.send/recv;
7.closesocket
8.释放WinSock资源
关闭套接字后,终止使用WInSock DLL,释放资源。
int WSACleanup(void); 若成功返回0.
二:客户端
1.加载库
2.创建套接字
3.connect
int connect(SOCKET s, const struct sockaddr FAR* name, int namelen);
name---指定服务器进程IP地址和端口。
4.recv/send
。。。。。