设计模式
文章目录
一、socket.h
接口(interface)
#ifndef SOCKET_H
#define SOCKET_H
#include <string>
using std::string;
class Socket
{
public:
Socket();
~Socket();
bool bind(int port);
bool listen(int backlog = 5);
int accept();
bool connect(const string &ip, int port); // ✅ 客户端连接方法
int fd() const { return m_sockfd; } // 可选:暴露 sockfd 方便客户端用
private:
int m_sockfd;
};
#endif // SOCKET_H
二、socket.cpp
实现(implementation)
// socket.cpp
#include "socket.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <cstdio>
#include <cerrno>
using std::string;
Socket::Socket()
{
m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
if (m_sockfd < 0)
{
printf("Socket creation failed: errno=%d, errmsg=%s\n", errno, strerror(errno));
}
}
Socket::~Socket()
{
if (m_sockfd >= 0)
{
::close(m_sockfd);
}
}
bool Socket::connect(const string &ip, int port)
{
sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (::inet_pton(AF_INET, ip.c_str(), &addr.sin_addr) <= 0)
{
printf("Invalid IP address: %s\n", ip.c_str());
return false;
}
int ret = ::connect(m_sockfd, (struct sockaddr*)&addr, sizeof(addr));
if (ret < 0)
{
printf("Connect failed: errno=%d, errmsg=%s\n", errno, strerror(errno));
return false;
}
return true;
}
void Socket::close()
{
if (m_sockfd >= 0)
{
::close(m_sockfd);
m_sockfd = -1;
}
}
三、server.cpp
使用封装(main 函数)
#include "socket.h"
#include <iostream>
#include <unistd.h> // read(), write()
#include <cstring> // memset
int main()
{
Socket server;
if (!server.bind(8888))
{
std::cerr << "Failed to bind port 8888" << std::endl;
return 1;
}
if (!server.listen())
{
std::cerr << "Failed to listen on port 8888" << std::endl;
return 1;
}
std::cout << "Server listening on port 8888..." << std::endl;
while (true)
{
int client_fd = server.accept();
if (client_fd < 0)
{
continue; // accept failed
}
char buffer[1024];
ssize_t n = ::read(client_fd, buffer, sizeof(buffer) - 1);
if (n > 0)
{
buffer[n] = '\0';
std::cout << "Received: " << buffer << std::endl;
std::string response = "Echo: ";
response += buffer;
::write(client_fd, response.c_str(), response.size());
}
::close(client_fd);
}
return 0;
}
四、client.cpp
使用封装(main 函数)
#include "socket.h"
#include <iostream>
#include <unistd.h> // read(), write()
#include <cstring> // strlen()
int main()
{
Socket client;
if (!client.connect("127.0.0.1", 8888))
{
std::cerr << "Failed to connect to server." << std::endl;
return 1;
}
std::cout << "Connected to server." << std::endl;
std::string input;
while (true)
{
std::cout << "Enter message: ";
std::getline(std::cin, input);
if (input == "exit")
break;
::write(client.fd(), input.c_str(), input.size());
char buffer[1024];
ssize_t n = ::read(client.fd(), buffer, sizeof(buffer) - 1);
if (n > 0)
{
buffer[n] = '\0';
std::cout << "Server response: " << buffer << std::endl;
}
else
{
std::cout << "Server closed connection." << std::endl;
break;
}
}
return 0;
}
五、退出方法
- 客户端:
当你在客户端输入:
Enter message: exit
客户端程序会退出(break
出循环)。
- 服务器:
- 当前版本是永不退出的死循环
- 你可以使用
Ctrl+C
来中断服务器进程
六、终端输出
- 终端 1:服务器
$ ./server
Server listening on port 8888...
Received: hello
Received: world
- 终端 2:客户端
$ ./client
Connected to server.
Enter message: hello
Server response: Echo: hello
Enter message: world
Server response: Echo: world
Enter message: exit