C 跨平台網路伺服器物件導向實現

2021-09-12 14:52:07 字數 3578 閱讀 2613

訊息標頭檔案messageheader.hpp

#ifndef _messageheader_hpp_

#define _messageheader_hpp_

enum cmd ;

// 訊息頭

struct dataheader ;

struct login :public dataheader

char username[32];

char password[32];

};struct loginresult : public dataheader

int result;

};struct logout :public dataheader

char username[32];

};struct logoutresult :public dataheader

int result;

};struct newuserjoin :public dataheader

int sock;

};#endif

主函式如下

#include "easytcpserver.hpp"

int main()

server.close();

printf("已退出。\n");

return 0;

}

初始化函式實現

// 初始化

void initsocket()

_sock = socket(af_inet, sock_stream, 0);

if (invalid_socket == _sock)

printf("錯誤,建立socket<%d>失敗...\n",_sock);

else

printf("建立socket<%d>成功...\n",_sock);

}

繫結埠函式 

// 繫結ip和埠號

socket bind(const char* ip, unsigned short port) ;

_sin.sin_family = af_inet;

_sin.sin_port = htons(9527);

#ifdef _win32

if (ip)

_sin.sin_addr.s_un.s_addr = inet_addr(ip);

else

_sin.sin_addr.s_un.s_addr = inaddr_any;

#else

if(ip)

_sin.sin_addr.s_addr = inet_addr(ip);

else

_sin.sin_addr.s_addr = inaddr_any;

#endif

int ret = bind(_sock, (sockaddr*)&_sin, sizeof(_sin));

if (socket_error == ret)

printf("錯誤,繫結網路埠<%d>失敗...\n", port);

else

printf("繫結埠<%d>成功...\n", port);

return _sock;

}

監聽函式

// 監聽埠號

int listen(int n)

檢測伺服器是伺服器是否在執行

// 判斷是否處在工作中

bool isrun()

通過select函式監聽客戶端連線,並接受客戶端通訊

bool onrun() 

timeval t = ; // 時間引數,非阻塞模式

// int ret = select(maxsock + 1, &fdread, &fdwrite, &fdexp, &t);

if (ret < 0)

if (fd_isset(_sock, &fdread))

for (int n = (int)g_clients.size() - 1; n >= 0; n--) }}

}} return isrun();

}

accept函式

// 接受客戶端連線

socket accept() ;

int naddrlen = sizeof(sockaddr_in);

socket _csock = invalid_socket;

#ifdef _win32

_csock = accept(_sock, (sockaddr*)&clientaddr, &naddrlen);

#else

_csock = accept(_sock, (sockaddr*)&clientaddr, (socklen_t*)&naddrlen);

#endif

if (invalid_socket == _csock)

printf("接受到無效客戶端socket...\n");

// 像其他客戶端傳送通知

else

return _csock;

}

recv函式

// 接受資料,處理粘包,拆分包

int recvdata(socket _csock)

; int nlen = recv(_csock, (char*)&szrecv, sizeof(dataheader), 0);

dataheader* header = (dataheader*)szrecv;

if (nlen <= 0)

recv(_csock, szrecv + sizeof(dataheader), header->datalength - sizeof(dataheader), 0);

onnetmsg(_csock, header);

return 0;

}

處理訊息函式

// 響應網路訊息

virtual void onnetmsg(socket _csock, dataheader* header)

break;

case cmd_logout:

break;

default:

dataheader header = ;

send(_csock, (char*)&header, sizeof(header), 0);

} }

傳送資料

// 傳送資料

int senddata(socket _csock, dataheader* header)

像所有客戶端傳送資料 

void senddatatoall(dataheader* header) 

}

最後關閉套接字

// 關閉套接字

void close()

}

關於網路伺服器

假如我有數千萬甚至是上億的使用者資料,我想把使用者自增id和使用者名稱username放到快取裡。我的需求是,當要查詢使用者的資訊時,我想先從快取裡根據使用者名稱username獲取到使用者的id,然後再通過id在資料庫裡查詢使用者的資訊。我想當乙個使用者表達到上億的數量級別時,用自增id來查詢肯定...

網路伺服器宕機

1.伺服器程序終止 當伺服器程序終止時,伺服器傳送fin給客戶端,客戶端回以ack,客戶端進入close wait狀態,但還沒有結束連線。此時客戶端阻塞於fgets,客戶端繼續傳送buffer,伺服器傳送rst,客戶端readline返回0。而如果客戶端不理睬readline返回的rst,繼續wri...

linux網路伺服器

在本次中,學習了乙個簡單的基於tcp ip的伺服器 客戶端。在例子中,利用的是af inet域。在linux下,最常用就是af inet,af unix.af unix是linux檔案系統實現的本地要借字。後面的是可以用於包括英特網在內的tcp ip網路通訊的程式。下面來看乙個簡單的基於tcp ip...