学习 TCP/IP 协议的时候,非常重要的一个内容就是利用socket进行通信,接下来贴出一个 点对点通信 的服务端代码与客户端代码,利用C++进行简单封装。
常用函数:
int socket(int domain, int type, int protocol);
bind(int sockfd, struct sockaddr * my_addr, int addrlen);
listen(int s, int backlog);
connect(int sockfd, struct sockaddr * serv_addr, int addrlen);
send(int s, const void * msg, int len, unsigned int falgs);
recv(int s, void *buf, int len, unsigned int flags);
int accept(int sockfd, struct sockaddr * addr, int * addrlen);
客户端程序 :
!!! **Lunix环境下**
/*
* 此程序演示socket的客户端
* 用c++的类封装socket
*/
#include
#include
#include
#include
#include
#include
#include
class TCPclient{
public:
TCPclient(){
sock_clientfp=0;
}
~TCPclient(){
if(sock_clientfp > 0 ){
close(sock_clientfp); //在析构函数中关闭socket
}
}
public:
bool connect_Server(const char *serverIP,int port); //连接服务端需要做的事情,也就是一些函数的使用和初始化
ssize_t Send(const void *buf, size_t len); //发送数据
ssize_t Recv(void *buf, size_t len); //接收数据
//这两个函数都会等待服务端的回复
private:
int sock_clientfp;
};
bool TCPclient::connect_Server(const char *serverIP,int port){
sock_clientfp = socket(AF_INET,SOCK_STREAM,0); //创建客户端的socket
struct hostent *h; //客户端ip地址的结构体
if((h = gethostbyname(serverIP)) == 0){
close(sock_clientfp);
sock_clientfp = 0;
return false;
}
//把服务器的地址和端口转换为数据结构体
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET; //协议族,在socket编程中只能是AF_INET
servaddr.sin_port = htons(port); //绑定通讯端口
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);
//向服务端发起连接请求
if(connect(sock_clientfp,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0){
close(sock_clientfp);
sock_clientfp = 0; //这里手动置零比较严谨
return false;
}
return true;
}
ssize_t TCPclient::Send(const void *buf, size_t len){
return send(Toclient_sock,buf,len,0);
}
ssize_t TCPclient::Recv(void *buf, size_t len){
memset(buf,0,len);
return recv(Toclient_sock,buf,len,0);
}
int main(){
TCPclient tcptest01; //构建一个对象
if(tcptest01.connect_Server("xxx.xxx.xx.xxx",5000)==false){
//xxx这里写你要连接的服务器IP地址
printf("连接服务器(xxx.xxx.xx.xxx) 失败!\n");
return -1;
}
//与服务端通信,发送一个报文后等待回复,然后等待下一个报文
char strbuffer[1024];
for(int i=1;i<20;i++){
memset(strbuffer,0,sizeof(strbuffer));
sprintf(strbuffer,"这是第%d个报文.",i);
if((tcptest01.Send(strbuffer,strlen(strbuffer))) <= 0){
//发送失败
break;
}
printf("发送: %s\n",strbuffer);
if(tcptest01.Recv(strbuffer,strlen(strbuffer)) <= 0){
//接收失败
break;
}
printf("接收: %s\n",strbuffer);
printf("\n");
}
return 0;
}
服务端程序:
**!!!Lunix环境下**
/*
* 此程序演示socket通讯服务端
* 用C++的类封装socket
*/
#include
#include
#include
#include
#include
#include
#include
class TCPserver{
public:
TCPserver(){
listen_sock = 0; //用于监听客户端是否有连接请求的socket
Toclient_sock = 0; //用于与客户端形成连接的socket
}
~TCPserver(){
if(listen_sock>0){
close(listen_sock);
}
if(Toclient_sock>0){
close(Toclient_sock);
}
}
public:
bool initserver(const int port); //初始化通信端口,也就是一些函数的使用
bool Accept(); //等待客户端发来连接请求
ssize_t Send(const void *buf, size_t len); //发送应答
ssize_t Recv(void *buf, size_t len); //接收数据
private:
int listen_sock;
int Toclient_sock;
};
bool TCPserver::initserver(const int port){
listen_sock = socket(AF_INET,SOCK_STREAM,0); //创建服务端的socket用于监听
//把服务端用于通讯的地址和端口绑定到socket
struct sockaddr_in servaddr; //服务端地址信息的结构体
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET; //协议族,在socket编程中只能是AF_INET
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //本主机任意IP地址都可以用于通讯
// servaddr.sin_addr.s_addr = inet_addr("192.168.15.128"); //绑定ip地址
servaddr.sin_port = htons(port); //绑定通讯端口
if(bind(listen_sock,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0){
close(listen_sock);
listen_sock = 0;
return false;
}
//把socket设置为监听模式
if(listen(listen_sock,5) != 0){
close(listen_sock);
listen_sock = 0;
return false;
}
return true;
}
bool TCPserver::Accept(){
if(Toclient_sock = accept(listen_sock,0,0)<0) //接收客户端的连接
return false;
return true;
}
ssize_t TCPserver::Send(const void *buf, size_t len){
return send(Toclient_sock,buf,len,0);
}
ssize_t TCPserver::Recv(void *buf, size_t len){
memset(buf,0,len);
return recv(Toclient_sock,buf,len,0);
}
int main(){
TCPserver test02;
if(test02.initserver(5000) == false){
printf("服务端初始化失败\n");
return -1;
}
if(test02.Accept() == false){
printf("服务端接受客户端的连接请求失败\n");
return -1;
}
//与客户端通信,接收客户端发过来的报文后 回复OK
char strbuffer[1024];
while(1){
if(test02.Recv(strbuffer,sizeof(strbuffer))<=0) //通讯断开
break;
printf("接收: %s\n",strbuffer);
strcpy(strbuffer,"我收到了.");
if(test02.Send(strbuffer,strlen(strbuffer))<=0)
break;
printf("发送: %s\n",strbuffer);
printf("\n");
}
return 0;
}