TCP流式套接字与I/O复用Select模型代码
C++的socket编程:实现了Server和Client端的通信,主要功能:
Server获取Client的system的时间,Server和Client互相收发文件
Server端代码:
#include "stdafx.h"
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include<windows.h>
#include<winsock2.h>
#include<iostream>
#include<ctime>
#include<time.h>
#include<ws2tcpip.h>
#include<stdlib.h>
#include<stdio.h>
#include<cstdio>
#include<cstring>
using namespace std;
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 1024
#define DEFAULT_PORT 30000
#define DEFAULT_DATA "Hello, I' m Mr.Trojan."
#define cmdline1 "GetTime"
#define cmdline2 "SendData"
#define cmdline3 "RecvData"
int main(int argc, _TCHAR* argv[]){
WSADATA wsaData;
int iResult;
SOCKET ServerSocket = INVALID_SOCKET, AcceptSocket = INVALID_SOCKET;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
sockaddr_in addrClient;
int addrClientlen = sizeof(sockaddr_in);
//Winsock初始化
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return -1;
}
// 创建监听套接字
ServerSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_IP);
if(ServerSocket == INVALID_SOCKET) {
printf("socket failed: %ld\n", WSAGetLastError());
WSACleanup();
return -1;
}
// 绑定地址和端口号
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(DEFAULT_PORT);
addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
iResult = bind(ServerSocket,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));
if (iResult == SOCKET_ERROR) {
printf("bind failed: %d\n", WSAGetLastError());
closesocket(ServerSocket);
WSACleanup();
return -1;
}
// 监听
iResult = listen(ServerSocket, SOMAXCONN);
if(iResult == SOCKET_ERROR) {
printf("listen failed !\n");
closesocket(ServerSocket);
WSACleanup();
return -1;
}
// 开启TCP连接
printf("TCP server starting\n");
fd_set fdRead,fdSocket;
FD_ZERO( &fdSocket );
FD_SET( ServerSocket, &fdSocket);
while(1){
//通过select等待数据到达事件
fdRead = fdSocket;
iResult = select( 0, &fdRead, NULL, NULL, NULL);
if (iResult >0){
//有网络事件发生
//确定有哪些套接字有未决的I/O,并进一步处理这些I/O
for (int i=0; i<(int)fdSocket.fd_count; i++){
if (FD_ISSET( fdSocket.fd_array[i] ,&fdRead)){
if( fdSocket.fd_array[i] == ServerSocket){
if( fdSocket.fd_count < FD_SETSIZE){
//同时复用的套接字数量最大为FD_SETSIZE
AcceptSocket = accept(ServerSocket,(sockaddr FAR*)&addrClient,&addrClientlen);
if( AcceptSocket == INVALID_SOCKET){
printf("accept failed !\n");
closesocket(ServerSocket);
WSACleanup();
return -1;
}
//复用等待
FD_SET( AcceptSocket, &fdSocket);
cout<<"Accept a new trojan:";
printf("%s", inet_ntoa(addrClient.sin_addr));
cout << " post: " << addrClient.sin_port << endl;
}
else{
printf("连接个数超限!\n");
continue;
}
}
else{
//数据
memset(recvbuf,0,recvbuflen);
iResult = recv( fdSocket.fd_array[i], recvbuf, recvbuflen, 0);
if (iResult > 0) {
//情况1:成功接收到数据
//printf("\nBytes received: %d\n", iResult);
cout<<recvbuf<<endl;
if (strcmp(recvbuf, DEFAULT_DATA)==0){
//将本地时间发送给客户端
char choose[DEFAULT_BUFLEN];
printf("-----------------------\n");
printf("-------1:GetTime-------\n");
printf("-------2:SendData------\n");
printf("-------3:RecvData------\n");
printf("-------q:Nothing-------\n");
printf("-----------------------\n");
scanf_s("%s",choose);
if (strlen(choose)==1){
if (choose[0] == '1'){
send(AcceptSocket, cmdline1, strlen(cmdline1), 0);
int err = recv(AcceptSocket, recvbuf, DEFAULT_BUFLEN, 0);
if (err > 0){
recvbuf[err] = '\0';
cout << recvbuf << endl;
}
}
else if (choose[0] == '2'){
send(AcceptSocket, cmdline2, strlen(cmdline2), 0);
scanf_s("%s",recvbuf);
int err = send(AcceptSocket,recvbuf,sizeof(recvbuf),0);
if (err > 0){
cout << "发送成功" << endl;
}
else{
cout << "发送失败" << endl;
}
}
else if (choose[0] == '3'){
send(AcceptSocket, cmdline3, strlen(cmdline3), 0);
int err = recv(AcceptSocket, recvbuf, DEFAULT_BUFLEN, 0);
if (err > 0){
recvbuf[err] = '\0';
cout << recvbuf << endl;
}
}
else if (choose[0] == 'q'){
//Do nothing
}
else{
puts("input error");
}
}
}
}
else if (iResult == 0) {
//情况2:连接关闭
printf("The trojan is dead.\n\n");
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i], &fdSocket);
}
else {
//情况3:接收失败
printf("recv failed with error: %d\n",WSAGetLastError() );
closesocket(fdSocket.fd_array[i]);
FD_CLR(fdSocket.fd_array[i], &fdSocket);
}
}
}
}
}
else{
printf("select failed with error: %d\n",WSAGetLastError() );
return -1;
}
}
// 关闭
closesocket(ServerSocket);
WSACleanup();
return 0;
}
Client端代码:
#include"stdafx.h"
#include<stdio.h>
#include<winsock2.h>
#include<wincrypt.h>
#include<time.h>
#include<cstring>
#include<iostream>
#include<string.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "shlwapi.lib")
using namespace std;
#define DEFAULT_IP "127.0.0.1"
#define DEFAULT_PORT 30000
#define DEFAULT_BUFLEN 1024
#define DEFAULT_DATA "Hello, I' m Mr.Trojan."
#define cmdline1 "GetTime"
#define cmdline2 "SendData"
#define cmdline3 "RecvData"
int Hello(SOCKET S){
SOCKET clientSocket = S;
int err;
err = send(clientSocket, DEFAULT_DATA, sizeof(DEFAULT_DATA), 0);
if (err > 0){
return 0;
}
return 1;
}
int main(){
int ConnectTimes = 20;
while(ConnectTimes--){
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
int error = WSAStartup(sockVersion, &wsaData);
if (error == -1){
cout << "fail to startup" << GetLastError() << endl;
WSACleanup();
return -1;
}
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
if (socketClient == INVALID_SOCKET){
cout << "socket error! " << GetLastError() << endl;
WSACleanup();
closesocket(socketClient);
return -1;
}
sockaddr_in addrServer;
addrServer.sin_addr.S_un.S_addr = inet_addr(DEFAULT_IP);
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(DEFAULT_PORT);
connect(socketClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));
Hello(socketClient);
char recvbuf[DEFAULT_BUFLEN];
memset(recvbuf, 0, sizeof(recvbuf));
recv(socketClient,recvbuf, DEFAULT_BUFLEN, 0);
if (strcmp(recvbuf,cmdline1)==0){
time_t t = time(0);
char currenttime[DEFAULT_BUFLEN];
strftime(currenttime, sizeof(currenttime), "%Y/%m/%d %X", localtime(&t));
printf_s("my currenttime is:%s\n",currenttime);
error = send(socketClient,currenttime,sizeof(currenttime),0);
if (error > 0){
cout << "发送成功" << endl;
}
else{
cout << "发送失败" << endl;
}
}
else if(strcmp(recvbuf,cmdline2)==0){
error = recv(socketClient,recvbuf, DEFAULT_BUFLEN, 0);
if (error > 0){
recvbuf[error] = '\0';
puts(recvbuf);
}
}
else if(strcmp(recvbuf,cmdline3)==0){
puts("input data:");
gets_s(recvbuf);
error = send(socketClient,recvbuf,sizeof(recvbuf),0);
if (error > 0){
cout << "发送成功" << endl;
}
else{
cout << "发送失败" << endl;
}
}
else{
//Nothing
}
closesocket(socketClient);
if (ConnectTimes % 2){
Sleep(300);
}
else{
Sleep(2000);
}
}
return 0;
}