在windows下创建一个socket,可以借助Winsock库来实现。
WSADATA是Windows Socket API的一个结构体,WSADATA结构体包含Winsock版本号\实现此Winsock服务的最高版本号。
描述此Winsock实现的可读字符串。提供实现的关于Winsock的需要的基本信息。
WORD wVer = MAKEWORD(2,2);
WSADATA lpWSAD;
int ret;
ret = WSAStartup(wVer, &lpWSAD);
if (ret != 0)
{
std::cout<<"Winsock error"<<std::endl;
return;
}
// 与MAKEWORD(2,2)中设定参数的作对比,有误退出
if ( LOBYTE( lpWSAD.wVersion ) != 2 || HIBYTE( lpWSAD.wVersion ) != 2 )
{
// 调用WSACleanup()函数来释放所占用的资源
std::cout<<WSACleanup()<< std::endl;
return;
}
初始化Winsock库之后需要创建socket对象
SOCKET sfd;
// 创建一个TCP网络套接字(socket),该套接字可以用于在网络上建立和管理TCP连接
sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sfd == INVALID_SOCKET)
{
cout<<"socket 创建失败"<<endl;
return -1;
}
struct sockaddr_in serveraddr;
memset(&serveraddr,0,sizeof(struct sockaddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(8000);
inet_pton(AF_INET, "192.168.154.123", &serveraddr.sin_addr);
SOCKET sfd
socket()函数
struct sockaddr_in serveraddr 是一个用于表示 IPv4 套接字地址的数据结构体。客户端或服务器端通过填写该结构体来指定通信对端的地址和端口号等信息。
//SOCKET sfd;
//struct sockaddr_in serveraddr;
// .... 填入IP地址和端口号
int ret;
ret = bind(sfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr));
if (ret == SOCKET_ERROR)
{
cout<<"bind error"<<endl;
return -1;
}
//SOCKET sfd;
//struct sockaddr_in serveraddr;
// .... 填入IP地址和端口号
int ret = listen(sfd, 10);
if (ret == SOCKET_ERROR)
{
cout<<"listen fail"<<endl;
return -1;
}
//SOCKET sfd;
//struct sockaddr_in serveraddr;
// .... 填入IP地址和端口号
SOCKET cfd;
struct sockaddr_in addr;
int addrlen = sizeof(struct sockaddr);
printf("accept 1\n");
// 用于接受客户端的连接请求并创建一个新的 socket 文件描述符
cfd = accept(sfd, (struct sockaddr *)&addr, &addrlen);//阻塞等待
printf("accept 2\n");
// INVALID_SOCKET 是在 Windows 平台上用于表示无效 socket 文件描述符的常量。在 Linux 和其他类 Unix 系统上,通常使用 -1 来表示无效的文件描述符。
if (cfd == INVALID_SOCKET)
{
cout<<"accept fail"<<endl;
return -1;
}
// SOCKET cfd;
// struct sockaddr_in addr;
char str[INET_ADDRSTRLEN];
std::cout <<"IP地址:" << inet_ntop(AF_INET, &(addr.sin_addr), str, INET_ADDRSTRLEN) << "端口号:"<<ntohs(addr.sin_port);
int con;
SOCKET sfd;
// socket函数创建套接字...
struct sockaddr_in serveraddr;
// 绑定端口
unsigned long ul=1;
con=ioctlsocket(sfd, FIONBIO, (unsigned long *)&ul);//将socket客户端connect设置成非阻塞模式。
if(con==SOCKET_ERROR)//如果设置失败。
{
printf("none block set fail\n");
}
//将sfd连接至指定的服务器网络地址 serveraddr
con = connect(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr));
if (con == SOCKET_ERROR)
{
cout<<"connect fail"<<endl;
return -1;
}
return sfd;
connect函数执行成功时返回0,失败时返回-1,并设置相应的错误代码。
unsigned long ul=1;
con=ioctlsocket(sfd, FIONBIO, (unsigned long *)&ul);
int ioctlsocket(
SOCKET s, //s:要操作的套接字的描述符。
long cmd, //cmd:指定要执行的操作的命令代码。
u_long* argp //包含有关此特定命令的参数的指向缓冲区的指针。
);
其中第二段参数
FIONBIO
非阻塞I/O模式。如果argp不为零,则将套接字设置为非阻塞模式。FIONREAD
可从套接字内读取的数据量(采用TCP)。argp是指向无符号长整型的指针。SIOCATMARK
此命令检查传输控制协议(TCP)套接字上是否存在特殊关注的边缘,也就是在接收到带外标记或OOB数据后是否还有要处理的数据。第三个变量
变量ul的初始值为1,这是由于无符号长整型是32位的,也就是在二进制下有32位,因此设置为1即为将第一位设置为1,表示“真”。这可以使套接字处于非阻塞模式中,避免阻塞在IO操作上。
如果操作成功,则返回值为0;否则返回SOCKET_ERROR并设置WSAGetLastError()以获得错误代码。