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
    评论
TCP服务器端程序设计一般分为以下几个步骤: 1. 创建套接字:使用系统调用socket()创建一个TCP套接字。 2. 绑定套接字:使用系统调用bind()将套接字与IP地址和端口号绑定在一起。 3. 监听连接请求:使用系统调用listen()开始监听客户端的连接请求。 4. 接受连接请求:使用系统调用accept()接受客户端的连接请求,创建新的套接字来处理该客户端的请求。 5. 与客户端通信:使用系统调用read()和write()与客户端进行通信,完成所需的数据传输。 6. 关闭套接字:使用系统调用close()关闭已经处理完毕的套接字。 下面是一个简单的TCP服务器端程序的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 8080 #define MAX_CLIENTS 5 int main() { int server_fd, new_socket, valread; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; char *hello = "Hello from server"; // 创建TCP套接字 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置套接字选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } // 绑定套接字 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons( PORT ); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接请求 if (listen(server_fd, MAX_CLIENTS) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 接受连接请求,并与客户端通信 while(1) { if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } valread = read( new_socket , buffer, 1024); printf("%s\n",buffer ); send(new_socket , hello , strlen(hello) , 0 ); printf("Hello message sent\n"); close(new_socket); } return 0; } ``` 以上代码实现了一个简单的TCP服务器端程序,它可以监听客户端的连接请求,并接受来自客户端的数据,在向客户端发送回应后关闭连接。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值