Socket网络编程(一)
此文使用的协议是 TCP
首先要写入以下代码,不然很多函数都用不了
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
●服务器端
第一步我们要导入套接字库。
WORD wVersionRequested = MAKEWORD(1, 1); WSADATA wsadata; int result = WSAStartup(wVersionRequested, &wsadata);
WORD有人可能不知道它是啥
看一看源代码就可以看到它是这样定义的
typedef unsigned short WORD //无符号短整数
还有WSAStartup函数,它的原型是这样的
int WSAStartup(WORD wVersionRequested,LPWSADATA IpWSAData);
第一个参数表示windows socket版本,高字节是修订版本号,低字节是主版本号;
第二个参数记录windows socket版本的相关信息,并且是指针变量;
这个函数有返回值,返回0时表示成功,其他值表示失败。
有时我们写服务器时为了防止套接字库加载错误可以写以下代码
if (result != 0) { printf("套接字加载失败!"); return 0; } if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) { printf("套接字版本错误!"); return 0; }
当然socket有不同的版本,这里只是做个示范
第二步创建套接字SOCKET
源代码是这样定义的
typedef unsigned int UINT_PIR typedef UINT_PIR SOCKET
所以SOCKET也是一个无符号整型数据
创建套接字要用到socket函数,函数原型是这样的
SOCKET _stdcall socket(int af,int type,int protocol)
af是address family的缩写,就是地址簇
type就是使用的协议类型,一共有三种
1、流式套接字(SOCK_STREAM):用到的协议TCP
2、数据包套接字(SOCK_DGRAM):无连接的,不可靠的UDP
3、原始套接字(SOCK_RAW)
而protocol就是与特定的地址簇相关的协议,一般填0就行了,现在举个例子
SOCKET sockSrv = socket( AF_INET //Internet 协议 地址簇 SOCK_STREAM, //套接字协议 0 //与特定的地址簇相关的协议 );
第三步绑定套接字
//bind绑定套接字,参数一服务器套接字,参数二服务器套接字地址,参数三套接字地址大小 SOCKADDR_IN sockaddr; sockaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(1234); if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR))) { printf("绑定套接字失败!"); return 0; };
那个 INADDR_ANY 表示的是任意地址的意思,因为服务器的地址是不确定的,所以填这个,当然你想改也可以改,只要改的对,还有端口随便找个不常用到的就行。
第四步将套接字设置为监听模式
// 参数一服务器套接字,参数二等待连接队列最大长度 if (SOCKET_ERROR == listen(sockSrv, 5)) { printf("监听失败!"); return 0; }
第五步接受客户端
// 参数一服务器套接字,参数二客户端套接字,参数三客户端套接字的长度 SOCKADDR_IN clientaddr; int nLength = sizeof(SOCKADDR); SOCKET sockcon = accept(sockSrv, (SOCKADDR*)&clientaddr, &nLength);
第六步发送/接受信息
函数原型int_stdcall send(SOCKET s,const char *buf,int len,int flags)
随便举个例子
char temp[100]; sprintf(temp, "欢迎 %s 进入聊天室!\n", inet_ntoa(clientaddr.sin_addr));//字符串是客户端的地址 send(sockCon, temp, strlen(temp) + 1, 0);
char temp[256]; recv(sockCon, tmep, 100, 0) printf("%s", temp);
最后要记得关闭套接字,不然有时会出现意外情况
closesocket(sock);
WSACleanup();
●客户端
第一步与服务器端一样加载套接字库,就不说了
第二步创建套接字
SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);
第三步连接服务器
SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//测试所以就用本地的了 addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(1234); //端口随便写一个1024之后的,也就是不常用的,不过要与服务器的一样 //参数一客户端套接字,参数二服务器地址信息,参数三套接字地址大小 if (SOCKET_ERROR == connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))) { printf("服务器连接失败!"); return 0; }
第四步发送/接受信息,与之前的一样,也不说了
当然最后也别忘了关闭套接字