120 lines
3.1 KiB
C++
120 lines
3.1 KiB
C++
![]() |
#include "tn.h"
|
||
|
using namespace std;
|
||
|
|
||
|
TN::TN() {
|
||
|
iofd = listenfd = 0;
|
||
|
}
|
||
|
TN::~TN() {
|
||
|
close(listenfd); //关闭连接
|
||
|
close(iofd); //关闭连接
|
||
|
}
|
||
|
|
||
|
int TN::server(const char *open_port, int connections) {
|
||
|
// 创建服务端socket
|
||
|
listenfd = socket(AF_INET, SOCK_STREAM, 0);
|
||
|
if(listenfd == -1)
|
||
|
return -1;
|
||
|
|
||
|
// 向客户端请求连接
|
||
|
memset(&servaddr, 0, sizeof(servaddr));
|
||
|
servaddr.sin_family = AF_INET;
|
||
|
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
|
||
|
servaddr.sin_port = htons(atoi(open_port)); //指定连接端口
|
||
|
|
||
|
// 解决端口重用问题
|
||
|
int opt = 1;
|
||
|
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt);
|
||
|
|
||
|
// 绑定服务端IP及端口
|
||
|
if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
|
||
|
return -1; // 绑定失败
|
||
|
|
||
|
// 把端口设为监听
|
||
|
if(listen(listenfd, connections) != 0) //第二个参数+1为已连接队列(已三次握手但没有accept)
|
||
|
return -1;
|
||
|
return s_accept();
|
||
|
}
|
||
|
int TN::client(const char *ip, const char *port) {
|
||
|
// 创建客户端socket
|
||
|
iofd = socket(AF_INET, SOCK_STREAM, 0);
|
||
|
if(iofd == -1)
|
||
|
return -1;
|
||
|
|
||
|
// 向服务端请求连接
|
||
|
if( (h = gethostbyname(ip)) == 0) // 指定ip地址
|
||
|
return -1;
|
||
|
memset(&servaddr, 0, sizeof(servaddr));
|
||
|
servaddr.sin_family = AF_INET;
|
||
|
servaddr.sin_port = htons(atoi(port)); //指定连接端口
|
||
|
memcpy(&servaddr.sin_addr, h->h_addr, h->h_length);
|
||
|
if(connect(iofd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) //发起连接请求
|
||
|
return -1; //连接失败
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int TN::s_accept() {
|
||
|
// 受理客户端连接请求, accept()阻塞等待
|
||
|
signal(SIGINT, TN_exit);signal(SIGTERM, TN_exit);
|
||
|
while(true) {
|
||
|
iofd = accept(listenfd, 0, 0);
|
||
|
if(iofd == -1) {
|
||
|
close(iofd); return -1; // 连接失败
|
||
|
}
|
||
|
int pid = fork();
|
||
|
if(pid == 0) { // 创建子进程处理连接
|
||
|
signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_DFL);
|
||
|
close(listenfd);
|
||
|
break;
|
||
|
}
|
||
|
else if(pid < 0) return -1;
|
||
|
else close(iofd);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int TN::out(char *str) {
|
||
|
if(send(iofd, str, strlen(str), 0) <= 0) // 发送报文
|
||
|
return -1; // 报文发送不成功
|
||
|
return 0;
|
||
|
}
|
||
|
int TN::in(char *str) {
|
||
|
//接收报文, recv()将阻塞等待
|
||
|
memset(str, 0, sizeof(str));
|
||
|
if(recv(iofd, str, sizeof(str), 0) <= 0)
|
||
|
return -1; // 未成功接收报文
|
||
|
return 0;
|
||
|
}
|
||
|
int TN::out(void *str, size_t fsize) {
|
||
|
if(send(iofd, str, fsize, 0) <= 0) // 发送报文
|
||
|
return -1; // 报文发送不成功
|
||
|
return 0;
|
||
|
}
|
||
|
int TN::in(void *str, size_t fsize) {
|
||
|
//接收报文, recv()将阻塞等待
|
||
|
memset(str, 0, fsize);
|
||
|
if(recv(iofd, str, fsize, 0) <= 0)
|
||
|
return -1; // 未成功接收报文
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
socklen_t TN::bufsize(size_t buf_send, size_t buf_recv) {
|
||
|
socklen_t optlen = sizeof(buf_send);
|
||
|
// 接收缓冲区大小
|
||
|
getsockopt(iofd, SOL_SOCKET, SO_SNDBUF, &buf_send, &optlen);
|
||
|
// 发送缓冲区大小
|
||
|
getsockopt(iofd, SOL_SOCKET, SO_RCVBUF, &buf_recv, &optlen);
|
||
|
return optlen;
|
||
|
}
|
||
|
|
||
|
int TN::nagle_off() {
|
||
|
int opt = 1;
|
||
|
setsockopt(iofd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void TN_exit(int sig) {
|
||
|
signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); //避免再次干扰
|
||
|
kill(0, SIGTERM); // 通知所有子进程退出
|
||
|
exit(0);
|
||
|
}
|