socket编程 服务器端编程

#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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值