TCP:Server-Client程序

来源:互联网 发布:范玮琪和张韶涵 知乎 编辑:程序博客网 时间:2024/05/01 18:43

服务器端程序:

//TCPServer.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <fcntl.h>
#include <netdb.h>
#include "ProtoStruct.h"
#include "SocketHandle.h"


static const int MAXPENDING = 3;


void dieWithSystemMessage(const char *msg)
{
perror(msg);
exit(1);
}








int main(int argc,char * argv[])
{
int sockSet[MAXPENDING] = {0};
for(int i = 0; i < MAXPENDING; i++)
{
sockSet[i] = 0;
}
SocHandler handleSet[MAXPENDING];
int maxDscriptor = 0;
int count = 0;
fd_set sockFDSet;
struct timeval selTimeout;
int ret;




if(argc != 2)
{
printf("please intput the server port \n");
return 0;
}



in_port_t servPort = atoi(argv[1]);


//create socket for incoming connection
int servSock;
if((servSock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
{
dieWithSystemMessage("create socket error");
}


//construct the local address structure
struct sockaddr_in servAddr;
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(servPort);


//bind to the local address
if(bind(servSock,(struct sockaddr *) & servAddr,sizeof(servAddr)) < 0)
{
dieWithSystemMessage("bind error");
}


//listen for incoming connections
if(listen(servSock,MAXPENDING) < 0)
{
dieWithSystemMessage("listen failed");
}


maxDscriptor = servSock;


while(1)
{
FD_ZERO(&sockFDSet);
FD_SET(servSock,&sockFDSet);


selTimeout.tv_sec = 30;
selTimeout.tv_usec = 0;


struct sockaddr_in clntAddr;
socklen_t clntAddrLen = sizeof(clntAddr);
char *contents;
int contLen;




for(int i = 0; i < MAXPENDING; i++)
{
if(sockSet[i] != 0)
{
FD_SET(sockSet[i],&sockFDSet);
}
}


ret = select(maxDscriptor + 1, &sockFDSet, NULL, NULL, &selTimeout);


if (ret < 0) 
{
perror("select");
break;



else if (ret == 0) 
{
printf("timeout\n");
continue;
}


for(int i = 0; i < count; i++)
{
if(FD_ISSET(sockSet[i],&sockFDSet))
{




handleSet[i].handle(sockSet[i],sockFDSet);

}
}




//wait for a client to connect
if(FD_ISSET(servSock,&sockFDSet))
{
int clntSock = accept(servSock,(struct sockaddr *) & clntAddr,&clntAddrLen);
if( clntSock < 0)
{
dieWithSystemMessage("accept failed ");
}

if(count < MAXPENDING)
{


sockSet[count++] = clntSock;


if(clntSock > maxDscriptor)
{
maxDscriptor = clntSock;
}


char clntName[INET_ADDRSTRLEN];
if(inet_ntop(AF_INET,&clntAddr.sin_addr.s_addr,clntName,sizeof(clntName)) != NULL)
{
printf("Handling client %s /%d \n",clntName,ntohs(clntAddr.sin_port));
}


else
{
puts("unable to get client address");
}


printf("handleTCPClient message \n");
}


}


}




for(int i = 0; i < MAXPENDING; i++)
close(sockSet[i]);



return 0;


}


///ProtoStruct.h

#ifndef PROTOSTRUCT_H
#define PROTOSTRUCT_H


const int CONTENTS_LEN = 512;
const int LOGIN = 1;
const int LOGOUT = 2;
const int REQUIRE = 3;
const int SENDMSG = 4;


struct Header
{
char name[2]; //源名称
unsigned short length;//内容长度/字节
int seq; //序列号
int ack; //确认号
int type; //操作类型


};


struct Body
{
char contents[CONTENTS_LEN];//内容
int crc; //校验码
};


struct Packet
{
Header header;
Body body;
};


#endif


///

SocketHandle.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <fcntl.h>
#include <netdb.h>
#include "ProtoStruct.h"


static const int BUFFER_SIZE = 1024 * 8;
const int Start = 0;
const int ReadHead = 1;
const int ParseHead = 2;
const int ReadBody = 3;
const int ParseBody = 4;
const int Done = 5;
const int headerSize = sizeof(Header);


class SocHandler
{
public:
char bufData[BUFFER_SIZE];
int state;
int index;
int totalBytes;
int numBytes;
Header recHeader;




public:
SocHandler();
void handle(int &sock,fd_set &sockFDSet);
};

///SocketHandle.cpp

#include "SocketHandle.h"


SocHandler::SocHandler()
{
memset(bufData,0,BUFFER_SIZE);
int state = Start;
int index = 0;
int totalBytes = 0;
int numBytes = 0;
//Header recHeader;
}


void SocHandler::handle(int &sock,fd_set &sockFDSet)
{
if(BUFFER_SIZE > index + totalBytes)
{
numBytes = recv(sock,bufData + index + totalBytes,BUFFER_SIZE - totalBytes,0);


printf("recv %d bytes \n",numBytes);


if(numBytes <= 0)
{
printf("client [%d] closed \n",sock);
close(sock);
FD_CLR(sock,&sockFDSet);
sock = 0;
}


else
{
totalBytes += numBytes;
}
}


int contLen = 0;
char *contents = NULL;


while(state != Done)
{
switch(state)
{
case Start:
if(totalBytes >= headerSize)
{
state = ParseHead;
break;
}


state = ReadHead;
break;


case ReadHead:


if(totalBytes >= headerSize)
{
state = ParseHead;
}


break;


case ParseHead:


memcpy(&recHeader,bufData + index,headerSize);
index += headerSize;
totalBytes -= headerSize;


contLen = recHeader.length;


printf("packet name : %s \n",recHeader.name);
printf("contents length:%d \n",recHeader.length);
printf("seq number is: %d \n",recHeader.seq);
printf("ack number is: %d \n",recHeader.ack);
printf("the operation type is: %d \n",recHeader.type);


if(totalBytes >= contLen)
{
state = ParseBody;
break;
}


state = ReadBody;


break;


case ReadBody:


if(index + totalBytes >= BUFFER_SIZE && totalBytes < contLen)
{
memcpy(bufData,bufData + index,totalBytes);
index = 0;
memset(bufData + totalBytes,0,BUFFER_SIZE - totalBytes);
}


if(totalBytes >= contLen)
{
state = ParseBody;
}
break;


case ParseBody:


contents = new char[contLen + 1];
memcpy(contents,bufData + index,contLen);
contents[contLen] = '\0';
index += contLen;
totalBytes -= contLen;
printf("totalBytes is: %d, index is : %d \n",totalBytes,index);
printf("contents is : %s \n",contents);
delete [] contents;


if(totalBytes < headerSize)
state = Done;


else
state = ParseHead;


break;


case Done:


if(index >= BUFFER_SIZE)
{
index = 0;
totalBytes = 0;
memset(bufData,0,BUFFER_SIZE);


state = Start;


break;
}


if(index + totalBytes >= BUFFER_SIZE)
{
if(totalBytes < headerSize)
{
memcpy(bufData,bufData + index,totalBytes);
index = 0;
memset(bufData + totalBytes,0,BUFFER_SIZE - totalBytes);
}


break;
}




default:
break;
}


if(state == ReadBody || state == ReadHead)
{
break;
}
}


if(state == Done)
state = Start;
}



客户端程序:

///TcpClient.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <fcntl.h>
#include <netdb.h>
#include <pthread.h>
#include "ProtoStruct.h"


static const int BUFFER_SIZE = 1024;


void dieWithSystemMessage(const char *msg)
{
perror(msg);
exit(1);
}






int main( int argc, char * argv[])
{
if( argc < 2 || argc > 3)
{
printf("please input the server addr and port \n");
return 0;
}


char * servIP = argv[1];
int pacSize = sizeof(Packet);
char buffer[pacSize];
char sendBuf[BUFFER_SIZE];
fd_set sockSet;
struct timeval selTimeout;
char bufData[BUFSIZ];
int sock;
in_port_t servPort = (argc == 3) ? atoi(argv[2]) : 7;
ssize_t numBytes;
Packet myPack;
Packet recPack;
Header header;
sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//create a socket


if(sock < 0)
dieWithSystemMessage("create socket failed");



struct sockaddr_in servAddr;//construct the server address structure
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
int rtnVal = inet_pton(AF_INET,servIP,& servAddr.sin_addr.s_addr);//convert address


if(rtnVal == 0)
dieWithSystemMessage("inet_pton failed");


servAddr.sin_port = htons(servPort);


//connection to the server
if(connect(sock, (struct sockaddr *) & servAddr,sizeof(servAddr)) < 0)
dieWithSystemMessage("connect failed");


//receive the same string back from the server
unsigned int totalBytesRcvd = 0;
fputs("Received: ",stdout);


while(1)
{
FD_ZERO(&sockSet);
FD_SET(STDIN_FILENO,&sockSet);
FD_SET(sock,&sockSet);

selTimeout.tv_sec = 30;
selTimeout.tv_usec = 0;


if(select(sock + 1,&sockSet,NULL,NULL,&selTimeout) == 0)
printf("No echo requests for %ld secs...Server still alive \n",30);


else
{
if(FD_ISSET(0,&sockSet))
{
gets(bufData);
size_t bufLen = strlen(bufData);


//construct the send packet
header.length = bufLen;
header.ack = 10;
header.seq = 1;
header.type = LOGIN;
header.name[0] = 'B';
header.name[1] = 'Y';


memcpy(sendBuf,&header,sizeof(Header));
memcpy(sendBuf + sizeof(Header),bufData,bufLen);


numBytes = send(sock,sendBuf,sizeof(header) + bufLen,0);


if(numBytes < 0)
{
dieWithSystemMessage("send () failed");
}


else if(numBytes != sizeof(Header) + bufLen)
{
dieWithSystemMessage("send() unexpected number of bytes");
}


printf("send %d bytes \n",numBytes);


memset(bufData,0,BUFSIZ);
memset(sendBuf,0,BUFFER_SIZE);
}


if(FD_ISSET(sock,&sockSet))
{
memset(buffer,0,pacSize);
numBytes = recv(sock,buffer,pacSize,0);


if(numBytes <= 0)
{
printf("server have closed \n");
FD_CLR(sock,&sockSet);
break;
}
int totalBytes = numBytes;
while(numBytes > 0 && totalBytes < pacSize)
{
numBytes = recv(sock,buffer + totalBytes,pacSize - totalBytes,0);


totalBytes += numBytes;
}


memcpy(&recPack,buffer,pacSize);


fputs(recPack.body.contents,stdout);
fputc('\n',stdout);
}
}



}



close(sock);


exit(0);


return 0;




}

原创粉丝点击