Tcp套接字的使用和Udp套接字的使用是差不多的,但是有一些地方还是有差别的,直接上代码
cpp
#pragma once
#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
std::string DefaultIp = "127.0.0.1";
int DefaultPort = 8080;
#define BACKLOG 5
class TcpSerevr
{
public:
TcpSerevr(const std::string& Ip = DefaultIp, const int &Port = DefaultPort)
//:_Ip(Ip)
:_Port(Port)
,_ListenSockFd(-1)
,_IsRuning(false)
{
}
void Init()
{
//创建套接字
_ListenSockFd = socket(AF_INET, SOCK_STREAM, 0);
if(_ListenSockFd < 0)
{
std::cout << "socket error: " << strerror(errno) << std::endl;
exit(1);
}
std::cout << "Socket success" << std::endl;
//初始化地址
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(_Port);
//local.sin_addr.s_addr = inet_addr(_Ip.c_str());
local.sin_addr.s_addr = INADDR_ANY;
//绑定
int n = bind(_ListenSockFd, (const struct sockaddr*)&local, sizeof(local));
if(n < 0)
{
std::cout << "bind error: " << strerror(errno) << std::endl;
exit(1);
}
std::cout << "bind sucess" << std::endl;
//设置监听
n = listen(_ListenSockFd, BACKLOG);
if(n < 0)
{
std::cout << "listen error: " << strerror(errno) << std::endl;
exit(1);
}
std::cout << "listen success" << std::endl;
}
void HanderRequest(int SockFd)
{
while(true)
{
char Buffer[1024];
ssize_t n = read(SockFd, Buffer, sizeof(Buffer)-1);
if(n > 0)
{
Buffer[n] = 0;
std::string EchoStr = "Server say:";
EchoStr += Buffer;
write(SockFd, EchoStr.c_str(), EchoStr.size());
}
}
}
void Start()
{
_IsRuning = true;
while(_IsRuning)
{
struct sockaddr_in Src;
socklen_t len = sizeof(Src);
int SockFd = accept(_ListenSockFd, (struct sockaddr*)&Src, &len);
if(SockFd < 0)
{
std::cout << "accept error: " << strerror(errno) << std::endl;
continue;
}
std::cout << "accept sucess" << std::endl;
HanderRequest(SockFd);
}
_IsRuning = false;
}
private:
//std::string _Ip;
int _Port;
int _ListenSockFd;
bool _IsRuning;
};
Init函数
在上面的init函数中,有这样一句代码
cpp
//设置监听
n = listen(_ListenSockFd, BACKLOG);
if(n < 0)
{
std::cout << "listen error: " << strerror(errno) << std::endl;
exit(1);
}
std::cout << "listen success" << std::endl;
因为Tcp协议是面向连接的,所以在初始化的时候需要监听
Start函数
在Start函数中,需要accept,其中,有个参数为sockfd类型的,返回值也是sockfd类型的,参数里面是用来监听的,返回的值是用为Tcp服务器服务
cpp
struct sockaddr_in Src;
socklen_t len = sizeof(Src);
int SockFd = accept(_ListenSockFd, (struct sockaddr*)&Src, &len);
客户端函数
cpp
#include <iostream>
#include <cstring>
#include <memory>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
if(argc != 3)
{
std::cout << "Usage ./TcpClient IP Port" << std::endl;
return 0;
}
std::string Ip = argv[1];
int Port = std::atoi(argv[2]);
int SockFd = socket(AF_INET, SOCK_STREAM, 0);
if(SockFd < 0)
{
std::cout << "socket error" << std::endl;
return 0;
}
std::cout << "socket sucess" << std::endl;
struct sockaddr_in ServerAddr;
memset(&ServerAddr, 0, sizeof(ServerAddr));
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(Port);
ServerAddr.sin_addr.s_addr = inet_addr(Ip.c_str());
int n = connect(SockFd, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
if(n < 0)
{
std::cout << "connect error" << std::endl;
return 0;
}
while(true)
{
std::string Message;
std::cout << "please send message#: ";
std::getline(std::cin, Message);
int n = write(SockFd, Message.c_str(), Message.size());
if(n > 0)
{
char Buffer[1024];
int m = read(SockFd, Buffer, sizeof(Buffer));
if(m > 0)
{
Buffer[m] = 0;
std::cout << Buffer << std::endl;
}
else
{
break;
}
}
else
{
break;
}
}
close(SockFd);
return 0;
}
客户端同样和Udp的有区别
cpp
int n = connect(SockFd, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
if(n < 0)
{
std::cout << "connect error" << std::endl;
return 0;
}
需要连接