TCP网络编程的基本流程
对于服务端,通常为以下流程:
- 调用
socket
函数创建socket
- 调用
bind
函数将socket
绑定到某个IP和端口上 - 调用
listen
开始监听 - 当有客户端请求连接上来时,调用
accept
函数接受连接,产生一个新的socket
- 基于新产生的
socket
调用send
或recv
函数,开始与客户端进行数据交流 - 通信结束后,调用
close
函数关闭套接字
对于客户端,通常为以下流程:
- 调用
socket
函数创建客户端socket
- 调用
connect
函数尝试连接服务器 - 连接成功后调用
send
或recv
函数,开始与服务器进行通信 - 通信结束后,调用
close
函数关闭socket
服务端代码实现如下:
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"
using std::cout;
using std::endl;
int main(int argc,char * argv[])
{
//1.create socket
int listenfd = socket(AF_INET,SOCK_STREAM,0);
if(listenfd == -1)
{
cout<<"create listenfd failed"<<endl;
return -1;
}
//2.Initialize server address
struct sockaddr_in bindaddr{};
bindaddr.sin_family =AF_INET;
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bindaddr.sin_port= htons(3000);
if (bind(listenfd,(struct sockaddr*) &bindaddr, sizeof(bindaddr)) == -1)
{
cout<<"bind listen socket failed!"<<endl;
return -1;
}
//3.Start listening
if(listen(listenfd,SOMAXCONN) == -1)
{
cout<<"listen error"<<endl;
return -1;
}
while (true)
{
sockaddr_in clientaddr{};
socklen_t clientaddrlen = sizeof(clientaddr);
//4.accept client connect
int clientfd = accept(listenfd,(struct sockaddr*)&clientaddr,&clientaddrlen);
if (clientfd != -1)
{
//5.Receive data from the client
char recvBuf[32]={0};
int ret = recv(clientfd,recvBuf,32,0);
if (ret > 0)
{
cout<<"Receive data from the client:"<<recvBuf<<endl;
ret = send(clientfd,recvBuf, strlen(recvBuf),0);
if(ret != strlen(recvBuf))
cout<<"send failed"<<endl;
else
cout<<"send successfully"<<endl;
}
else
{
cout<<"Receive data error"<<endl;
}
close(clientfd);
}
}
//7.close listen
close(listenfd);
return 0;
}
#pragma clang diagnostic pop
客户端代码
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 3000
#define SEND_DATA "helloworld"
int main(int argc,char *argv[])
{
//1.create socket
int clientfd = socket(AF_INET,SOCK_STREAM,0);
if(clientfd == -1)
{
std::cout<<"create socket failed"<<std::endl;
return -1;
}
//2.connect server
sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr= inet_addr(SERVER_ADDRESS);
serveraddr.sin_port= htons(SERVER_PORT);
if (connect(clientfd,(struct sockaddr*) &serveraddr, sizeof(serveraddr)) == -1)
{
std::cout<<"connect socket error"<<std::endl;
return -1;
}
//3. send data to server
int ret= send(clientfd,SEND_DATA, strlen(SEND_DATA),0);
if (ret != strlen(SEND_DATA))
{
std::cout<<"send data failed"<<std::endl;
return -1;
}
std::cout<<"successfully"<<SEND_DATA<<std::endl;
//4.recv data from server
char recvBuf[32] ={0};
ret = recv(clientfd,recvBuf,32,0);
if(ret >0)
{
std::cout<<"sucessfully"<<std::endl;
} else
{
std::cout<<"failed"<<recvBuf<<std::endl;
}
//5.close socket
close(clientfd);
return 0;
}
TCP网络编程的基本流程
Linux与C++11多线程编程(学习笔记)
Linux select函数用法和原理
socket的阻塞模式和非阻塞模式(send和recv函数在阻塞和非阻塞模式下的表现)
connect函数在阻塞和非阻塞模式下的行为
获取socket对应的接收缓冲区中的可读数据量