Winsock编程基础2(Winsock编程流程)

时间:2023-01-07 03:33:19
1、套接字的创建和关闭
//创建套接字
SOCKET socket(
int af, //指定套接字使用的地址格式,Winsock只支持AF_INET
int type, //套接字类型
int protocol//配合type使用,使用的协议
);
//---type
/*
* SOCKET_STREAM 流套接字,TCP
* SOCKET_DGRAM 数据报套接字UDP
* SOCK_RAW 原始套接字
*/
//type使用上面两种时,protocol可直接赋0
//创建失败返回 INVALID_SOCKET(-1),可通过WSAGetLastError获得错误代码
//也可以使用WSASocket创建套接字,现在先不讨论 //关闭套接字
int closesocket(SOCKET s); //s为要关闭套接字句柄
 2、绑定IP和端口号
int bind(
SOCKE s, //套接字句柄
const struct socketaddr* name, //要关联的本地地址
int nameLen //地址长度
);
//bind作用在没有建立连接的套接字上 //绑定示例
//填充sockaddr_in结构
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(); //为0时主机也会自动配置
addr.sin_addr.S_un.S_addr = INADDR_ANY; //自动使用当前主机配置
//绑定这个套接字到一个本地地址
if(bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)//sListen是一个套接字
{
cout << "Failed bind()" << endl;
return ;
}
 3、设置套接字进入监听状态
int listen(
SOCKET s, //套接字句柄
int backlog //监听队列中允许保持的尚未处理的最大连接数,队满客户端会收到WSAECONNREFUSED
);

4、接受连接请求

SOCKET accept(        //返回实际连接的套接字,与s有相同属性
SOCKET s,
struct sockaddr* addr, //指向sockassr_in结构指针,用于获得对方信息
int *addrLen //指向地址长度指针
);

5、客户端创建套接字后的请求与服务器连接

int connect(
SOCKET s, //客户端套接字
const struct sockaddr FAR *name, //包含了要连接的服务器的地址信息
int nameLen
);

6、收发数据

int send(
SOCKET s, //
const char FAR *buf, //要发送的数据缓冲区地址
int Len, //缓冲区长度
int flags //调用方式,常设0
);
int recv(SOCKET s, char FAR *buf, int len, int flags)

简单实例

//服务器端
#include <iostream>
#include <stdio.h> #include "InitSock.h" using namespace std;
int main(void)
{
CInitSock initSock;
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
cout << "Failed socke()" << endl;
return ;
}
//填充sockaddr_in结构
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons();
addr.sin_addr.S_un.S_addr = INADDR_ANY;
//绑定这个套接字到一个本地地址
if (bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
{
cout << "Failed bind()" << endl;
return ;
} //进入监听模式
if (listen(sListen, ) == SOCKET_ERROR)
{
cout << "Failed listen()" << endl;
return ;
} //循环接受客户端连接请求
sockaddr_in remoteAddr; //远程客户端信息
int nAddrLen = sizeof(remoteAddr);
SOCKET sClient;
char szText[] = "TCP Sever Demo!\r\n";
while (true)
{//接受新连接
sClient = accept(sListen, (SOCKADDR *)&remoteAddr, &nAddrLen);
if (sClient == INVALID_SOCKET)
{
cout << "Failed accept()" << endl;
continue;
} cout << "接受一个连接: " << inet_ntoa(remoteAddr.sin_addr) <<endl;; //inet_ntoa()实际已过时,只能处理IPv4
//向客户端发送数据
send(sClient, szText, strlen(szText), );
//关闭通客户端的连接
closesocket(sClient);
}
//关闭监听套接字
closesocket(sListen);
return ;
}

客户端

#include <iostream>
#include <stdio.h> #include "InitSock.h" using namespace std;
int main(void)
{
CInitSock initSock;
//创建套接字
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
cout << "Failed socke()" << endl;
return ;
}
//也可以在这里调用binding函数绑定一个本地连接
//否则系统会自动安装
//...
//填写远程地址信息
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons();
servAddr.sin_addr.S_un.S_addr = INADDR_ANY; //注意这里要填写远程服务器的TCP地址
//本地回环127.0.0.1
servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -)
{
cout << "Failed connect()" << endl;
return ;
} //接受数据
char buff[];
int nRecv = recv(s, buff, , );
if (nRecv > )
{
buff[nRecv] = '\0';
cout << buff << endl;
}
//关闭套接字
closesocket(s);
getchar();
return ;
}