Socket TCP服务器端程序

相关代码: windows 下 socket tcp 连接.

1. Windows 下需添加 Socket API
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2, 2); //声明调用不同的Winsock版本,(2.2)即2.2版
//绑定相应socket库
if(WSAStartup(wVersion, &wsaData) != NO_ERROR) //NO_ERROR==0
    return false;

不同Winsock版本区别:1.1版只支持TCP/IP协议,2.0版可以支持多协议
(2.0版有良好的向后兼容性,任何使用1.1版的源代码、二进制文件、应用程序都可以不加修改地在2.0规范下使用。)
此外Winsock 2.0支持异步 1.1不支持异步.

结束时,需要解除与Socket库的绑定并且释放Socket库所占用的系统资源:

int WSACleanup (void);

*编译时如果报错:

错误 “error LNK2019: 无法解析的外部符号 _WSAStartup@8,该符号在函数 _main 中被引用”

错误原因:缺少相应库
解决方法:添加 #pragma comment(lib,“ws2_32.lib”)

2. 创建 socket 套接字
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

参数2:TCP连接设为 SOCK_STREAM
,UDP连接设为 SOCK_DGRAM
参数3:TCP连接设为 IPPROTO_TCP,UDP连接设为 IPPTOTO_UDP
返回值:成功返回套接字,错误返回 INVALID_SOCKET

3. 绑定服务器本地 IP 和 端口号
char ip[] = "192.168.0.110";
char port[] = "40000";
sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
inet_pton(AF_INET, ip, &serv_addr.sin_addr.S_un.S_addr);
serv_addr.sin_port = htons(atoi(port));
int ret = bind(fd, (sockaddr *)& serv_addr, sizeof(serv_addr));

返回值:成功返回 0,错误返回 -1

4. 设置监听
int ret = listen(fd, 1);

参数2:等待连接队列的最大长度
返回值:成功返回 0,错误返回 -1

5. 等待客户端连接
sockaddr_in client_addr; //接收客户端信息
socklen_t addrlen = sizeof(client_addr);
int clientfd = accept(fd, (struct sockaddr *) &client_addr, &addrlen);

等待客户端 connect()
返回值:成功返回描述符(通讯使用),错误返回INVALID_SOCKET

6. 发送 和 接收
send(clientfd, msg, msglen, 0);

返回值:成功发送数据个数,错误返回 SOCKET_ERROR

recv(clientfd, msg, msglen, 0);

返回值:成功接收数据个数,错误返回 SOCKET_ERROR
如果需要接收的数据过大,可以设置固定接收长度,循环接收。

7. 关闭套接字
closesocket(clientfd);
closesocket(fd);
8. setsockopt 设置

(1) 设置收发超时

int nNetTimeout = 5000; //ms
//设置接收时限
setsockopt(m_iConnfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
//设置发送时限
setsockopt(m_iConnfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout, sizeof(int));

(2) 设置心跳

int keepalive = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive));
  • 如果通信两端超过 2 个小时没有交换数据,那么开启 keep-alive 的一端会自动发一个 keep-alive 包给对端。
  • 如果对端正常的回应 ACK 包,那么一切都没问题,再等个 2 小时后发包(如果这两个小时仍然没有数据交换)。
  • 如果对端回应 RST 包,表明对端程序崩溃或重启,这边 socket 产生 ECONNRESET 错误,并且关闭。
  • 如果对端一直没回应,这边会每 75 秒再发包给对端,总共发 8 次共 11 分钟 15 秒。最后 socket 产生 ETIMEDOUT 错误,并且关闭。或者收到 ICMP 错误,表明主机不可到达,则会产生 EHOSTUNREACH 错误。

windows 下心跳设置:

#include <MSTcpIP.h>

tcp_keepalive alive_in;
tcp_keepalive alive_out;
alive_in.keepalivetime     = 8000; //检测心跳时间间隔
alive_in.keepaliveinterval = 400;  //无回复重发时间间隔
alive_in.onoff             = true;
unsigned long ulBytesReturn = 0;
WSAIoctl(dlg->listen_sock, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in), &alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);

连接断开后 send 和 recv 会即可返回,不会阻塞。

9. 失败报错

如果连接或通讯中函数返回错误,可通过 WSAGetLastError () 查询错误代码。

int errnum = WSAGetLastError();

错误代码说明链接.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值