在客户端建立连接套接字的顺序如下:
1 .创建套接字
如g_ClientSocket = socket(AF_INET,SOCK_STREAM,0);
函数SOCKET socket( int af,int type,int protocol);
af 指定协议的地址族。
type 协议的套接字类型。
protocol 协议字段,当指定了地址族和套接字类型后,该值的取值范围就确定了。默认情况下为0。
2 . 设置客户端socket异步选择标志,异步事件包括:连接,读,写,关闭等
WSAAsyncSelect(g_ClientSocket,hWnd,CLIENT_MESSAGE,FD_READ|FD_WRITE|FD_CLOSE|FD_CONNECT);
WinSock通过异步选择函数WSAAsyncSelect实现非阻塞通信。由该函数对指定窗口中某个Socket对象指定某种网络事件。当
被指定的网络事件发生时,WinSock将发送由程序事先约定的消息到指定的消息接收窗口。
int WSAAsyncSelect(
SOCKET s, //选择的套接字
HWND hWnd, //接收消息窗口的句柄
unsigned int wMsg, //发送到接收窗口的消息
long lEvent //被指定的网络事件
);
3. 设置服务器的地址和端口
addr.sin_family = AF_INET; //网络层采用IP协议
addr.sin_addr.S_un.S_addr = inet_addr(serverIP);//将标准点格式IP地址转换为long型网络地址
addr.sin_port = htons(port); //将主机short型端口号转换成网络型
描述通信对象地址的结构体
struct sockaddr_in{
short sin_family; //地址族
unsigned short sin_port; //端口号
struct in_addr sin_addr; //指定的IP地址
char sin_zero[8]; //冗余字段,目的使sockaddr_in结构和SOCKADDR结构大小相同
};
4. 连接服务器
connect(g_ClientSocket, (sockaddr*)&addr, sizeof(addr));
int connect(
SOCKET s, //连接的Socket
const struct sockaddr* name, //sockaddr名字的指针
int namelen
);
在服务器端建立连接套接字的顺序如下:
1 .创建套接字
如g_ClientSocket = socket(AF_INET,SOCK_STREAM,0);
2 . 设置客户端socket异步选择标志,异步事件包括:连接,读,写,关闭等
WSAAsyncSelect(g_ClientSocket,hWnd,SERVER_MESSAGE,FD_READ|FD_WRITE|FD_CLOSE|FD_CONNECT);
3 . 设置监听信息
addr.sin_family = AF_INET; //IP layer takes IP router protocol
addr.sin_addr.S_un.S_addr = INADDR_ANY; //任选本机某个网卡的IP地址
addr.sin_port = htons(port);//port from short of host to short of network
4.绑定监听socket
bind(g_ListenSocket, (sockaddr*)&addr, sizeof(sockaddr);
5. 开始监听
int listen(SOCKET s,int backlog);
backlog 是并发连接等待队列的长度.
具体的网络消息的处理
可以用宏WSAGETSELECTERROR来检测错误,需要利用参数lParam的高字节.而具体的消息类型则存储在lParam的低字节,宏WSAGETSELECTEVENT用来获取该低字节值.
getpeername 将SOCKET的信息存储在SOCKADDR结构体中
int getpeername(
SOCKET s,
struct sockaddr* name, //The SOCKADDR structure that receives the name of the peer.
int* namelen
);
send函数发送数据到连接的SOCKET.
int send(
SOCKET s,
const char* buf, //存储发送数据的buffer
int len, //buf中的数据长度,按字节计数
int flags //Indicator specifying the way in which the call is made.
);
由于异步流方式的套接字并不能保证对请求的数据量的读写,所以重载一个新的发送函数.
void Send(SOCKET sock, const char* buffer, int length)
{
int ret,i;
i=0;
while(length>0)
{
ret=send(sock,&(buffer[i]),length,0);
if(ret==0)
break;
else if(ret == SOCKET_ERROR)
{
g_ChatWords+="Error sending./r/n";
break;
}
length-=ret;
i+=ret;
}
}
上述函数每次发送一定量的数据,逐步将数据发送完毕.