#include <Winsock2.h>
#include <stdio.h>
void main()
{
WORD wVersionRequested; //定义一个WORD类型变量
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2); //请求一个(2,2)版本库,第一个是高位字节,第二个是低位字节 MAKEWOED是一个宏获得wVersionRequested的准确值
err = WSAStartup(wVersionRequested, &wsaData); //此函数加载套接字库,进行套接字库的版本协商,即确定我们使用的是哪个版本的套接字库
//第一个参数指定使用的版本号,第二个是返回一个指向WSADATA结构体的指针,跟库版本有关的信息存入,接收Windows实现的详细的细节
if (err != 0)
{
return;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判断返回的低字节和高字节是不是为2
{
WSACleanup(); //不是我们所请求的版本,那就直接退出调用socket库
return;
}
//创建套接字
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); //定义套接字变量接收socket套接字返回一个SOCKET套接字描述符,实际就是一个整型。 第一个参数指定地址族,TCP/IP套接字只能写成AF_INET/PF_INET
//第二个参数是指定socket类型,1,1版本socket,只支持SOCK_STREAM 和SOCK_DGRAM,第三个参数一般为0;
//将套接字绑定到本地地址和端口上
SOCKADDR_IN addrSrv;//地址结构体变量 sockaddr结构定义 TCP/IP中经常用sockaddr_in替换sockaddr,方便填写地址信息
//对地址结构体成员进行赋值 使用htonl讲u_long;类型将主机字节序转换为TCP/IP网络字节序
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 有sin_family,表示地址家族,除了他都要使用网络字节序,对于IP地址必须为AF_INET,和sa_data,表示要求一块内存分配区
addrSrv.sin_family = AF_INET;
//htons将short类型转换为TCP/IP网络字节序
addrSrv.sin_port = htons(6000); //sin_port指定的是将要分配给套接字的端口(网络字节顺序表示) sin_zero只是一个填充数,以使sockaddr_in和sockaddr结构长度一样,
//sin_addr给出的是套接字的主机IP地址(网络字节顺序表示)
//将本地地址和端口与套接字关联起来
//上面使用的是SOCKADDR_IN,所以下面需要使用(SOCKADDR*)进行强制转换
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//第一个参数为指定要绑定的套接字,第二个参数指定了该套接字的本地地址信息,是指向sockaddr结构的指针变量
//由于该地址结构是为所有的地址家族准备的,这个结构可能随所使用的网络协议不同而不同,所以用第三个参数指定该地址结构的长度
//将套接字设置为监听模式,监听连接请求
//第二个参数为等待连接队列的最大长度 如有三个客户请求,而最大长度为2,则有两个会被放到请求对列,第三个则会被拒绝
listen(sockSrv, 5);
SOCKADDR_IN addrClient; //定义一个地址结构体变量,用来接收地址结构体的信息
int len = sizeof(SOCKADDR); //定义一个变量是它初始化为地址结构体的长度,不初始化赋值下面的调用将会失败
while (1) //为一个客户服务完成之后,服务器端返回继续监听下一个请求,因此客户端可以不断的去启动
{
//接收用户的连接请求,此时套接字sockSrv属于被监听模式,并返回一个SOCKET套接字描述符,
//addrClient保存了当客户端像服务器端发起连接时,保存了向服务器端发起连接的客户端的IP地址和端口信息
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
//定义一个Buffer字符数组
char sendBuf[100];
//将一个数据格式化到Buffer中
sprintf(sendBuf, "Welcome %s to http:/", inet_ntoa(addrClient.sin_addr));
/*
如果我们只想让套接字使用多个IP中的一个地址,就必须指定实际地址,要做到这一点,可以使用inet_addr()函数
这个函数需要一个字符串作为其参数,还字符串指定了以点分十进制格式表示的IP地址(如192.168.1.13)。
而且inet_addr()函数会返回一个适合分配给S_addr的数字。
inet_ntoa()函数会完成想反的转换,它接受一个in_addr结构体类型参数并返回一个以点分十进制格式表示的IP地址字符串
*/
//发生建立连接的套接字,而不使用处于监听状态下的套接字 下面+1目的是最后增加一个\0结尾
send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
//定义字符数字接收
char recvBuf[100];
//接收数据
recv(sockConn, recvBuf, 100, 0);
printf("%s\n", recvBuf);
//通信结束之后关闭套接字
closesocket(sockConn);
}
}
#include <stdio.h>
void main()
{
WORD wVersionRequested; //定义一个WORD类型变量
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2); //请求一个(2,2)版本库,第一个是高位字节,第二个是低位字节 MAKEWOED是一个宏获得wVersionRequested的准确值
err = WSAStartup(wVersionRequested, &wsaData); //此函数加载套接字库,进行套接字库的版本协商,即确定我们使用的是哪个版本的套接字库
//第一个参数指定使用的版本号,第二个是返回一个指向WSADATA结构体的指针,跟库版本有关的信息存入,接收Windows实现的详细的细节
if (err != 0)
{
return;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//判断返回的低字节和高字节是不是为2
{
WSACleanup(); //不是我们所请求的版本,那就直接退出调用socket库
return;
}
//创建套接字
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); //定义套接字变量接收socket套接字返回一个SOCKET套接字描述符,实际就是一个整型。 第一个参数指定地址族,TCP/IP套接字只能写成AF_INET/PF_INET
//第二个参数是指定socket类型,1,1版本socket,只支持SOCK_STREAM 和SOCK_DGRAM,第三个参数一般为0;
//将套接字绑定到本地地址和端口上
SOCKADDR_IN addrSrv;//地址结构体变量 sockaddr结构定义 TCP/IP中经常用sockaddr_in替换sockaddr,方便填写地址信息
//对地址结构体成员进行赋值 使用htonl讲u_long;类型将主机字节序转换为TCP/IP网络字节序
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 有sin_family,表示地址家族,除了他都要使用网络字节序,对于IP地址必须为AF_INET,和sa_data,表示要求一块内存分配区
addrSrv.sin_family = AF_INET;
//htons将short类型转换为TCP/IP网络字节序
addrSrv.sin_port = htons(6000); //sin_port指定的是将要分配给套接字的端口(网络字节顺序表示) sin_zero只是一个填充数,以使sockaddr_in和sockaddr结构长度一样,
//sin_addr给出的是套接字的主机IP地址(网络字节顺序表示)
//将本地地址和端口与套接字关联起来
//上面使用的是SOCKADDR_IN,所以下面需要使用(SOCKADDR*)进行强制转换
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//第一个参数为指定要绑定的套接字,第二个参数指定了该套接字的本地地址信息,是指向sockaddr结构的指针变量
//由于该地址结构是为所有的地址家族准备的,这个结构可能随所使用的网络协议不同而不同,所以用第三个参数指定该地址结构的长度
//将套接字设置为监听模式,监听连接请求
//第二个参数为等待连接队列的最大长度 如有三个客户请求,而最大长度为2,则有两个会被放到请求对列,第三个则会被拒绝
listen(sockSrv, 5);
SOCKADDR_IN addrClient; //定义一个地址结构体变量,用来接收地址结构体的信息
int len = sizeof(SOCKADDR); //定义一个变量是它初始化为地址结构体的长度,不初始化赋值下面的调用将会失败
while (1) //为一个客户服务完成之后,服务器端返回继续监听下一个请求,因此客户端可以不断的去启动
{
//接收用户的连接请求,此时套接字sockSrv属于被监听模式,并返回一个SOCKET套接字描述符,
//addrClient保存了当客户端像服务器端发起连接时,保存了向服务器端发起连接的客户端的IP地址和端口信息
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
//定义一个Buffer字符数组
char sendBuf[100];
//将一个数据格式化到Buffer中
sprintf(sendBuf, "Welcome %s to http:/", inet_ntoa(addrClient.sin_addr));
/*
如果我们只想让套接字使用多个IP中的一个地址,就必须指定实际地址,要做到这一点,可以使用inet_addr()函数
这个函数需要一个字符串作为其参数,还字符串指定了以点分十进制格式表示的IP地址(如192.168.1.13)。
而且inet_addr()函数会返回一个适合分配给S_addr的数字。
inet_ntoa()函数会完成想反的转换,它接受一个in_addr结构体类型参数并返回一个以点分十进制格式表示的IP地址字符串
*/
//发生建立连接的套接字,而不使用处于监听状态下的套接字 下面+1目的是最后增加一个\0结尾
send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
//定义字符数字接收
char recvBuf[100];
//接收数据
recv(sockConn, recvBuf, 100, 0);
printf("%s\n", recvBuf);
//通信结束之后关闭套接字
closesocket(sockConn);
}
}