客户端:
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
int iRet = 0;
int iSocket = -1;
int iClientFd = -1;
int iTcpPort = 0;
char *pcTcpAddr = NULL;
static unsigned int suiNo = 0;
socklen_t stCliAddrLen = 0;
struct sockaddr_in stCliAddr;
fd_set stFdSet, stReadFdSet;
char *arrDataBuff[1024000] = {0};
struct timeval stTv;
if(3 != argc){
cout << "Usage :\n cli <ip_addr> <port>" << endl;
return -1;
}
else{
iTcpPort = atoi(argv[2]);
pcTcpAddr = argv[1];
}
iSocket = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == iSocket){
cout << "Socket error!" << endl;
return -1;
}
bool bReuseaddr = true;
setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&bReuseaddr, sizeof(bool));
setsockopt(iSocket,IPPROTO_TCP, TCP_NODELAY, (char *)&bReuseaddr, sizeof(bool));
stTv.tv_sec = 2;
stTv.tv_usec = 0;
setsockopt(iSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&stTv, sizeof(stTv));
struct linger stLinger;
stLinger.l_onoff = 1;
stLinger.l_linger = 0;
setsockopt(iSocket, SOL_SOCKET, SO_LINGER, (char *)&stLinger, sizeof(struct linger));
stCliAddr.sin_family = AF_INET;
stCliAddr.sin_port = htons(iTcpPort);
stCliAddr.sin_addr.s_addr = inet_addr(pcTcpAddr);
if(0 != connect(iSocket, (sockaddr *)&stCliAddr, sizeof(stCliAddr))){
cout << "Connect error!" << endl;
return -1;
}
FD_ZERO(&stFdSet);
FD_SET(iSocket, &stFdSet);
while(true){
memset(arrDataBuff, 0x23, sizeof(arrDataBuff));
iRet = write(iSocket, arrDataBuff, sizeof(arrDataBuff));
if(iRet < 0){
cout << "Write error!" << endl;
}
#if 0
stTv.tv_sec = 5;
stTv.tv_usec = 0;
stReadFdSet = stFdSet;
iRet = select(iSocket+1, &stReadFdSet, NULL, NULL, &stTv);
cout << "iRet = " << iRet << endl;
if(0 >= iRet){
continue;
}
memset(arrDataBuff, 0x00, sizeof(arrDataBuff));
iRet = read(iSocket, arrDataBuff, sizeof(arrDataBuff));
if(0 > iRet){
cout << "Read error!" << endl;
close(iSocket);
}
else if(0 == iRet){
}
else{
iRet = write(iSocket, arrDataBuff, sizeof(arrDataBuff));
if(iRet < 0){
cout << "Write error!" << endl;
}
}
#endif
}
getchar();
close(iSocket);
return 0;
}
服务端:
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
int i = 0;
int iRet = 0;
int inRead = 0;
int iCount = 0;
int iOpts = 0;
int iSocket = -1;
int iEpollFd = -1;
int iClientFd = -1;
int iTcpSvrPort = 0;
char chRcvBuff[1024] = {0};
socklen_t stCliAddrLen = 0;
struct epoll_event stEvent;
struct epoll_event arrEv[1024];
struct sockaddr_in stSvrAddr, stCliAddr;
if(2 == argc){
iTcpSvrPort = atoi(argv[1]);
cout << "TCP Server Port = " << iTcpSvrPort << endl;
}
bzero(&stSvrAddr, sizeof(stSvrAddr));
bzero(&stCliAddr, sizeof(stCliAddr));
//创建本地SOCKET
iSocket = socket(AF_INET, SOCK_STREAM, 0);
if(0 >= iSocket){
cout << "Get socket handler error!" << endl;
return -1;
}
//绑定监听端口
stSvrAddr.sin_family = AF_INET;
if(0 == iTcpSvrPort){
stSvrAddr.sin_port = htons(20015);
}
else{
stSvrAddr.sin_port = htons(iTcpSvrPort);
}
//绑定所有地址端口
stSvrAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//设置描述符属性
iOpts = fcntl(iSocket, F_GETFL);
if(iOpts < 0){
cout << "Opts getfl error!" << endl;
return -1;
}
iOpts = iOpts | O_NONBLOCK;
if(fcntl(iSocket, F_SETFL, iOpts) < 0){
cout << "Opts setfl error!" << endl;
return -1;
}
//让close立即返回,避免产生TIME_WAITE状态
struct linger stLinger;
stLinger.l_onoff = 1; //允许等待
stLinger.l_linger = 0; //等待时间设置为0,即不等待
iRet = setsockopt(iSocket, SOL_SOCKET, SO_LINGER, (char *)&stLinger, sizeof(struct linger));
if(0 > iRet){
cout << "Setsockopt error!" << endl;
}
iRet = bind(iSocket, (struct sockaddr *)&stSvrAddr, sizeof(struct sockaddr));
if(0 != iRet){
close(iSocket);
return -1;
}
iRet = listen(iSocket, 255);
if(0 != iRet){
close(iSocket);
return -1;
}
/*套接字监控*/
//创建epoll监听fd
iEpollFd = epoll_create(1024); //监听最大数量
if(0 >= iEpollFd){
cout << "Epoll creat error!" << endl;
return -1;
}
stEvent.data.fd = iSocket;
//stEvent.events = EPOLLIN | EPOLLET; //边缘触发
stEvent.events = EPOLLIN;
epoll_ctl(iEpollFd, EPOLL_CTL_ADD, iSocket, &stEvent);
/*数据接收*/
while(true){
memset(arrEv, 0x00, sizeof(arrEv));
iCount = epoll_wait(iEpollFd, arrEv, 16, 1);
for(i = 0; i < iCount; i++){
//在iSocket上有事件发生,说明有新客户端连接
if(arrEv[i].data.fd == iSocket){
stCliAddrLen = sizeof(struct sockaddr);
iClientFd = accept(iSocket, (struct sockaddr *)&stCliAddr, &stCliAddrLen);
if(0 > iClientFd){
cout << "Accept client error!" << endl;
}
/*把客户端加入到EPOLL中*/
//设置描述符属性
iOpts = fcntl(iClientFd, F_GETFL);
if(iOpts < 0){
cout << "[Client]Opts getfl error!" << endl;
return -1;
}
iOpts = iOpts | O_NONBLOCK;
if(fcntl(iClientFd, F_SETFL, iOpts) < 0){
cout << "[Client]Opts setfl error!" << endl;
return -1;
}
stEvent.data.fd = iClientFd;
//stEvent.events = EPOLLIN | EPOLLET; //EPOLLET边沿触发,事件未处理一直触发
stEvent.events = EPOLLIN; //EPOLLIN有可读数据
epoll_ctl(iEpollFd, EPOLL_CTL_ADD, iClientFd, &stEvent);
}
else if(arrEv[i].events & EPOLLIN){
memset(chRcvBuff, 0x00, sizeof(chRcvBuff));
inRead = read(arrEv[i].data.fd, chRcvBuff, sizeof(chRcvBuff));
if(errno == EINTR){
cout << "Error : EINTR" << endl;
}
if(inRead < 0){
cout << "Read error" << endl;
//删除EPOLL监控事件
stEvent.data.fd = arrEv[i].data.fd;
stEvent.events = EPOLLIN;
epoll_ctl(iEpollFd, EPOLL_CTL_DEL, arrEv[i].data.fd, &stEvent);
if (-1 != arrEv[i].data.fd){
close(arrEv[i].data.fd);
}
}
else if(0 == inRead){
}
else{
iRet = write(arrEv[i].data.fd, chRcvBuff, inRead);
if(iRet < 0){
cout << "Send data error!" << endl;
}
}
}
}
}
return 0;
}
转载自原文链接, 如需删除请联系管理员。
原文链接:TCP通讯:客户端和服务端,转载请注明来源!