生活随笔
收集整理的這篇文章主要介紹了
网络编程套接字(三)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
網(wǎng)絡(luò)編程套接字(三)
文章目錄
- 網(wǎng)絡(luò)編程套接字(三)
- 一、實(shí)現(xiàn)簡(jiǎn)單的Tcp服務(wù)器(單用戶)
一、實(shí)現(xiàn)簡(jiǎn)單的Tcp服務(wù)器(單用戶)
#pragma once
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <string>#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>typedef struct sockaddr sockaddr
;
typedef struct sockaddr_in sockaddr_in
;#define CHECK_RET(exp) if(!(exp)){\return false;\
}class TcpSocket
{public:TcpSocket():fd_(-1){}TcpSocket(int fd
):fd_(fd
){}bool Socket(){fd_
= socket(AF_INET
,SOCK_STREAM
,0);if(fd_
< 0){perror("socket is error");return false;}printf("socket fd is successful! fd = %d\n",fd_
);return true;}bool Close(){printf("close fd! fd = %d ",fd_
);close(fd_
);return true;}bool Bind(const std
::string
& ip
,uint16_t port
){sockaddr_in addr
;addr
.sin_family
= AF_INET
;addr
.sin_addr
.s_addr
= inet_addr(ip
.c_str());addr
.sin_port
= htons(port
);int ret
= bind(fd_
,(sockaddr
*)&addr
,sizeof(addr
));if(ret
< 0){perror("bind is error");return false;}return true;}bool Listen(int num
= 5){int ret
= listen(fd_
,num
);if(ret
< 0){perror("listen is error");return false;}return true;}bool Accept(TcpSocket
* peer
,std
::string
* ip
= nullptr,uint16_t* port
= nullptr){sockaddr_in peer_addr
;socklen_t len
= sizeof(peer_addr
);int new_sock
= accept(fd_
,(sockaddr
*)&peer_addr
,&len
);if(new_sock
< 0){perror("accept is error");return false;}printf("accept new fd! fd = %d\n",new_sock
);peer
->fd_
= new_sock
;if(ip
!= nullptr){*ip
= inet_ntoa(peer_addr
.sin_addr
); }if(port
!= nullptr){*port
= ntohs(peer_addr
.sin_port
);}return true;}int Recv(std
::string
* buf
){buf
->clear();char temp
[1024 * 10]= {0};ssize_t read_size
= recv(fd_
,temp
,sizeof(temp
),0);if(read_size
< 0){perror("recv is error");return -1;}if(read_size
== 0){return 0;}buf
->assign(temp
,read_size
);return 1;}bool Send(const std
::string
& buf
){ssize_t write_size
= send(fd_
,buf
.data(),buf
.size(),0);if(write_size
< 0){perror("send is error");return false;}return true;}bool Connect(const std
::string
& ip
,uint16_t port
){sockaddr_in addr
;addr
.sin_family
= AF_INET
;addr
.sin_addr
.s_addr
= inet_addr(ip
.c_str());addr
.sin_port
= htons(port
);int ret
= connect(fd_
,(sockaddr
*)&addr
,sizeof(addr
));if(ret
< 0){perror("connect is error");return false;}return true;}int GetFd(){return fd_
;}private:int fd_
;
};
#pragma once
#include <functional>
#include "tcp_socket.hpp"typedef std
::function
<void (const std
::string
& req
, std
::string
* resp
)> Handler
;class TcpServer
{public:TcpServer(const std
::string ip
,uint16_t port
):ip_(ip
),port_(port
){}bool Start(Handler handler
){CHECK_RET(listen_sock_
.Socket());CHECK_RET(listen_sock_
.Bind(ip_
,port_
));CHECK_RET(listen_sock_
.Listen());while(1){TcpSocket new_sock
;std
::string ip
;uint16_t port
;if(!listen_sock_
.Accept(&new_sock
,&ip
,&port
)){continue;}printf("[client %s : %d ]connect!",ip
.c_str(),port
);while(1){std
::string req
;int ret
= new_sock
.Recv(&req
);if(ret
< 0){printf("[client %s : %d]disconnect!\n",ip
.c_str(),port
);continue;}if(ret
== 0){printf("[client %s : %d]關(guān)閉了鏈接!\n",ip
.c_str(),port
);new_sock
.Close();break;}printf("client say : [%s : %d]\n",ip
.c_str(),port
);std
::string resp
;handler(req
,&resp
);new_sock
.Send(resp
);printf("[%s:%d] req: %s, resp: %s\n", ip
.c_str(), port
,req
.c_str(), resp
.c_str());}}return true;}private:TcpSocket listen_sock_
;std
::string ip_
;uint16_t port_
;
};
#pragma once
#include "tcp_socket.hpp"class TcpClient
{public:TcpClient(const std
::string
& ip
, uint16_t port
) : ip_(ip
), port_(port
) {sock_
.Socket();}~TcpClient() {sock_
.Close();}bool Connect() {return sock_
.Connect(ip_
, port_
);}bool Recv(std
::string
* buf
) {return sock_
.Recv(buf
);}bool Send(const std
::string
& buf
) {return sock_
.Send(buf
);}private:TcpSocket sock_
;std
::string ip_
;uint16_t port_
;};
#include <unordered_map>
#include "tcp_server.hpp"std
::unordered_map
<std
::string
, std
::string
> g_dict
;void Translate(const std
::string
& req
, std
::string
* resp
)
{auto it
= g_dict
.find(req
);if (it
== g_dict
.end()) {*resp
= "未找到";return;}*resp
= it
->second
;return;
}#if 0
int main(int argc
, char* argv
[])
{if (argc
!= 3) {printf("Usage ./dict_server [ip] [port]\n");return 1;}g_dict
.insert(std
::make_pair("hello", "你好"));g_dict
.insert(std
::make_pair("world", "世界"));g_dict
.insert(std
::make_pair("bit", "賊NB"));TcpServer
server(argv
[1], atoi(argv
[2]));server
.Start(Translate
);return 0;
}
#endifint main()
{g_dict
.insert(std
::make_pair("hello", "你好"));g_dict
.insert(std
::make_pair("world", "世界"));g_dict
.insert(std
::make_pair("bit", "賊NB"));TcpServer
server("0.0.0.0",9090);server
.Start(Translate
);return 0;
}
#include "tcp_client.hpp"
#include <iostream>int main(int argc
, char* argv
[])
{if (argc
!= 3) {printf("Usage ./dict_client [ip] [port]\n");return 1;}TcpClient
client(argv
[1], atoi(argv
[2]));bool ret
= client
.Connect();if (!ret
) {return 1;}for (;;) {std
::cout
<< "請(qǐng)輸入要查詢的單詞:" << std
::endl
;std
::string word
;std
::cin
>> word
;client
.Send(word
);std
::string result
;client
.Recv(&result
);std
::cout
<<word
<<" 意思是:"<< result
<< std
::endl
;}
return 0;
}
總結(jié)
以上是生活随笔為你收集整理的网络编程套接字(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。