前言
把tcp连接封装成类,建立面向对象的编程思维,利用多线程可以让tcp服务与多个tcp客户建立连接并通信
重点
- accept()会堵塞进程,直到检测到新连接,所以需要把accpet放到循环中
- 在线程中传递参数时,把建立好连接的对象传递过去
- 注意关闭连接
完整代码脚本
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
class SocketTcpServer
{
private:
int sk;
string ip;
int port;
bool status;
struct sockaddr_in s_addr;
public:
SocketTcpServer()
{
ip = "0.0.0.0";
port = 8080;
sk = 0;
status = false;
s_addr.sin_family = AF_INET; // 协议族,在socket编程中只能是AF_INET
s_addr.sin_addr.s_addr = inet_addr(ip.c_str());
s_addr.sin_port = htons(port); // 绑定通讯端口
}
SocketTcpServer(string ip_, int port_)
{
ip = ip_;
port = port_;
sk = 0;
status = false;
s_addr.sin_family = AF_INET; // 协议族,在socket编程中只能是AF_INET
s_addr.sin_addr.s_addr = inet_addr(ip.c_str());
s_addr.sin_port = htons(port); // 绑定通讯端口
}
void tcpTalk(int cl)
{
char buf[1024] = {0};
while(1) {
int rd = read(cl, buf, sizeof(buf));
if (rd == -1) {
perror("read");
exit(-1);
} else if(rd > 0) {
for (int i=0; i< rd; i++) {
printf("%d ", buf[i]);
}
printf("\n");
} else if (rd == 0) {
cout << "client close" << endl;
close(cl);
break;
}
char const *data= "hello, iam server";
write(cl, data, strlen(data));
}
}
void openTcp()
{
sk = socket(AF_INET, SOCK_STREAM, 0);
if (sk == -1) {
perror("socket");
exit(-1);
}
int opt = 1;
setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
int res = bind(sk, (struct sockaddr *)&s_addr, sizeof(s_addr));
if (res == -1) {
perror("bind");
exit(-1);
} else {
cout << "bind success!" << endl;
}
res = listen(sk, 5);
if(res == -1) {
perror("listen");
exit(-1);
} else {
cout << "listening ..." << endl;
}
struct sockaddr_in c_addr;
socklen_t c_addr_len = sizeof(c_addr);
while (true)
{
int sk_client = accept(sk, (struct sockaddr *)&c_addr, &c_addr_len);
if (sk_client == -1) {
perror("accept");
exit(-1);
}
printf("connect : %s %d\n", inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port));
thread(&SocketTcpServer::tcpTalk, this, sk_client).detach();
}
close(sk);
}
};
int main()
{
SocketTcpServer s("192.168.1.103", 10000);
s.openTcp();
while (true)
{
this_thread::sleep_for(chrono::milliseconds(200));
}
return 0;
}