socket中文翻译是套接字,但是这样并不好理解,还是把它比喻为多人通话好一点.
socket中的服务器:如果只有两人通话的时候,其实不能叫做服务器,直接叫对讲机好了,就是我们互相连接,然后你发信息给我,我再发信息给你.这也是最简单的一种socket编程.如果想像QQ群那样群聊,就需要一个”真正”的服务器了,因为这时候你需要一个中转站来把客户端发来的消息都分发给各个客户端.
它的头文件和库是:WinSock32.h , ws2_32.lib
服务器端:
初始化套接字(WSAStartup)->创建套接字(socket)->绑定服务器(bind)->监听有无客户端请求连接(listen)->接受连接请求(accept)->接受/发送数据(recv/send)->关闭服务器(closesocket,WSACleanup).
1.初始化套接字,也是获取套接字.
WSADATA是一个存放套接字信息的结构
利用WSAStartup函数来获取套接字信息并且存放到WSADATA
int WSAStartup(
WORD wVersionRequested, //需要的版本
LPWSADATA lpWSAData //套接字信息结构
);
获取到套接字信息后还要判断是否获取的是2.2版本的.
方法如下:
//判断版本
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("wVersion was not 2.2\n");
return -1;
}
2.创建套接字
//成功返回一个套接字,失败返回INVLID_SOCKET
SOCKET socket(
int af, // AF 表示ADDRESS FAMILY 地址族
int type, //套接字的类型
int protocol//使用的传输协议
);
其中af的值可以是如下几个常用的:
AF_UNIX(本机通信)
AF_INET(TCP/IP – IPv4)
AF_INET6(TCP/IP – IPv6)
type的值可以是如下几个:
SOCK_STREAM(TCP流)
SOCK_DGRAM(UDP数据报)
SOCK_RAW(原始套接字)
3.绑定服务器地址
//成功返回0,失败返回SOCKET_ERROR
int bind(
SOCKET s, //要绑定的套接字
const struct sockaddr FAR* name,//服务器的地址
int namelen //长度
);
其中第二个参数的使用,例如:
SOCKADDR_IN ServerAddr = { 0 };//服务端地址
ServerAddr.sin_family = AF_INET;//连接方式
ServerAddr.sin_port = htons(uPort);//服务器监听端口
ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任何客户端都能连接这个服务器
然后要需要转型:(SOCKADDR*)&ServerAddr
htons:本机(h)to(转换)成网络(n)字节短整型(s)
htonl:本机(h)to(转换)成网络(n)字节长整型(l)
4.监听有无客户端申请连接
//成功返回0,失败返回SOCKET_ERROR
int listen(
SOCKET s,
int backlog //表示可以连接的客户端个数
);
5.接受客户端请求
//成功就返回一个新的客户端套接字
SOCKET accept(
SOCKET s,
struct sockaddr FAR* addr,//获取客户端的地址
int FAR* addrlen //客户端地址的长度
);
6.接受/发送消息
//成功返回接受到的bytes,连接关闭则返回0,失败返回SOCKET_ERROR
int recv(
SOCKET s, //第5步返回的新客户端连接
char FAR* buf,//接收数据的缓存区
int len, //缓存区大小
int flags //设为0
);
//成功返回发送的bytes失败返回SOCKET_ERROR
int send(
SOCKET s, //第5步返回的新客户端连接
const char FAR* buf,//要发送的数据
int len, //数据的长度
int flags //设为0
);
7.关闭所有连接并清理
//成功返回0,失败返回SOCKET_ERROR
int closesocket(
SOCKET s
);
WSACleanup();//清理