实例介绍
【实例简介】创建TCP服务器,开启连接TCP客户端的线程;将TCP服务器接收的消息发送给各个客户端线程连接的TCP服务器
【实例截图】
【核心代码】
// MainServer.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #define MAX_LOADSTRING 100 #define MTIMER_ID WM_USER 1 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); // Client Manage Member #pragma warning(disable:4068) #pragma warning(disable:4786) #include<iostream> #include<string> #include<map> using namespace std; // Main HWND m_hWnd; RECT m_Rect; BOOL m_bShowClient; BOOL m_bDrawClient; int m_nPageIndex; // HDC Member // Server Function #pragma comment(lib, "Ws2_32.lib") #include <stdio.h> #include <WinSock2.h> #include <WS2tcpip.h> #include <process.h> #define _BUFFER_LENGTH_ 1024 #define _DEFAULT_PORT_ 12345 //数量统计计数 typedef struct _Count_Stru { UINT nCientNum; UINT nRcvThreadNum; UINT nRcvPagesNum; UINT nRcvBytesSize; UINT nRcvAllBytesSize; }CountStru; CountStru m_CountInfo; //数据包结构 typedef struct _PAGEDATA { UINT DataNo; UINT DataSum; UINT DataOneSize; UINT DataAllSize; char DataBuf[1024]; }PAGEDATA; typedef struct _CLIENT_INFO { SOCKADDR_IN mSOCKADDR_IN; SOCKET mSOCKET; int nSize; BOOL bState; }Client_Info; map<int,Client_Info> m_ClientMap; // 服务器状态 typedef struct _SERVER_STATE { BOOL bServerState; //服务状态 LONG lHeartNum; //接收心跳数量 LONG lRecvNum; //接收指令数据数量 }Server_State; Server_State m_ServerState; //初始化信息 void InitParams(void); //结束时释放 void FreeParams(void); //显示信息 void DrawInfo(HDC); //处理接收信息 void ParseMsg(SOCKET,char*,int); //接收客户端消息的线程函数 unsigned __stdcall ThreadRecv(LPVOID param) { SOCKET sockClient = (SOCKET)param; int nRecv=0; UINT nAllSize=0; int i=0; map<int,Client_Info>::iterator iter; char mRcv[1024]={0}; while(SOCKET_ERROR!=nRecv) { //按照消息结构接收数据 //ZeroMemory(&mPageData,sizeof(PAGEDATA)); //nRecv=recv(sockClient,(char*)&mPageData,sizeof(PAGEDATA),0); //一般接收 ZeroMemory(mRcv,1024); nRecv=recv(sockClient,mRcv,1024,0); //MessageBox(NULL,"HELLO","ERROR",MB_OK); if(SOCKET_ERROR == nRecv || 0==nRecv) { m_bDrawClient=FALSE; //关闭Socket shutdown(sockClient, SD_BOTH); closesocket(sockClient); for(i=0,iter=m_ClientMap.begin();iter!=m_ClientMap.end();iter ,i ) { Client_Info mClientInfo= (Client_Info)iter->second; if(sockClient==mClientInfo.mSOCKET) { //m_ClientMap.erase(iter); mClientInfo.bState=FALSE; iter->second=mClientInfo; //::InvalidateRect(m_hWnd,&m_Rect,FALSE); //break; } } m_bDrawClient=TRUE; ::InvalidateRect(m_hWnd,&m_Rect,FALSE); //标记当前线程为有信号 _endthreadex(0); } else if(0<nRecv) { //处理接收的信息 ParseMsg(sockClient,mRcv,nRecv); //修改发送人信息 map<int,Client_Info>::iterator iter; for(iter=m_ClientMap.begin();iter!=m_ClientMap.end();iter ) { Client_Info mClientInfo= (Client_Info)iter->second; if(sockClient==mClientInfo.mSOCKET) { mClientInfo.nSize=nRecv; iter->second=mClientInfo; } } ::InvalidateRect(m_hWnd,&m_Rect,FALSE); } } return 0; } //接受客户端的连接 unsigned __stdcall ThreadAccept(LPVOID param) { SOCKET ListenSocket = (SOCKET)param; while(TRUE) { SOCKET sockClient = INVALID_SOCKET; //printf("start accept...\n"); SOCKADDR_IN addrClient; int nAddrLen=sizeof(SOCKADDR); sockClient = accept(ListenSocket, (SOCKADDR*)&addrClient,&nAddrLen); //sockClient = accept(ListenSocket, NULL,NULL); if(INVALID_SOCKET == sockClient) { //printf("accept failed:%d\n", WSAGetLastError()); } else { m_CountInfo.nCientNum =1; unsigned threadId; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadRecv,(void*)sockClient, 0, &threadId); Client_Info mClientInfo; mClientInfo.nSize=0; mClientInfo.mSOCKADDR_IN=addrClient; mClientInfo.mSOCKET=sockClient; mClientInfo.bState=TRUE; m_ClientMap.insert(pair<int,Client_Info>(m_CountInfo.nCientNum,mClientInfo)); ::InvalidateRect(m_hWnd,&m_Rect,FALSE); m_CountInfo.nRcvThreadNum =1; } } closesocket(ListenSocket); WSACleanup(); return 0; } int StartServer(void) { //Initialize Server Socket Settting int err; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2,2); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return 0; WSACleanup(); } // Initialize Server Socket SOCKET sockSrv=INVALID_SOCKET; sockSrv=socket(AF_INET,SOCK_STREAM,0); if(INVALID_SOCKET == sockSrv) { //printf("Error at socket(): %d\n", WSAGetLastError()); WSACleanup(); return 0; } SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(_DEFAULT_PORT_); // Bind Server Socket err=bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); if(err == SOCKET_ERROR) { //printf("bind failed: %d\n", WSAGetLastError()); closesocket(sockSrv); WSACleanup(); return 0; } // Listen Server Socket if(listen(sockSrv, SOMAXCONN) == SOCKET_ERROR) { //printf("Error at bind():%d \n", WSAGetLastError()); closesocket(sockSrv); WSACleanup(); return 0; } //while(true) { unsigned threadId; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadAccept,(void*)sockSrv, 0, &threadId); m_ServerState.bServerState=TRUE; //printf("waitting for ClinetSocket to finish...\n"); //WaitForSingleObject(hThread, INFINITE);// 直到线程有信号为止 //CloseHandle(hThread); } //WSACleanup(); return 0; } int StopServer(void) { WSACleanup(); return 0; } // int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_MAINSERVER, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MAINSERVER); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_MAINSERVER); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW 1); wcex.lpszMenuName = (LPCSTR)IDC_MAINSERVER; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { //HWND hWnd; hInst = hInstance; // Store instance handle in our global variable m_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW&~WS_MAXIMIZEBOX&~WS_THICKFRAME, CW_USEDEFAULT, 0, 600, 400, NULL, NULL, hInstance, NULL); if (!m_hWnd) { return FALSE; } ShowWindow(m_hWnd, nCmdShow); InitParams(); UpdateWindow(m_hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; POINT mPt; //TCHAR szHello[MAX_LOADSTRING]; //LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); char chMsg[100]=""; UINT iDex=0; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: if(IDOK==MessageBox(hWnd,_T("确认要退出服务器程序吗?"),_T("系统提示"),MB_ICONQUESTION|MB_OKCANCEL)) { DestroyWindow(hWnd); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... DrawInfo(hdc); EndPaint(hWnd, &ps); break; case WM_LBUTTONDOWN: mPt.x = LOWORD(lParam); mPt.y = HIWORD(lParam); if(mPt.x>m_Rect.right-400 && mPt.y>m_Rect.bottom-66) { if(mPt.x>m_Rect.right-362 && mPt.x<m_Rect.right-308) { m_nPageIndex=0; //MessageBox(hWnd,"1","ok",MB_OK); } if(mPt.x>m_Rect.right-298 && mPt.x<m_Rect.right-244) { int nPageCount=0; if(0==m_ClientMap.size()%48) { nPageCount=m_ClientMap.size()/48; } else { nPageCount=m_ClientMap.size()/48 1; } if(m_nPageIndex<nPageCount-1) { m_nPageIndex ; } //MessageBox(hWnd,"2","ok",MB_OK); } if(mPt.x>m_Rect.right-146 && mPt.x<m_Rect.right-90) { if(m_nPageIndex>0) { m_nPageIndex--; } //MessageBox(hWnd,"3","ok",MB_OK); } if(mPt.x>m_Rect.right-80 && mPt.x<m_Rect.right-12) { int nPageCount=0; if(0==m_ClientMap.size()%48) { nPageCount=m_ClientMap.size()/48; } else { nPageCount=m_ClientMap.size()/48 1; } if(nPageCount>0) { m_nPageIndex=nPageCount-1; } //MessageBox(hWnd,"4","ok",MB_OK); } } else { if(mPt.x>0 && mPt.x<m_Rect.right && mPt.y>26 && mPt.y<52) { m_bShowClient=!m_bShowClient; } else { m_bShowClient=FALSE; } } ::InvalidateRect(hWnd,&m_Rect,FALSE); break; case WM_LBUTTONUP: break; case WM_CLOSE: if(IDOK==MessageBox(hWnd,_T("确认要退出服务器程序吗?"),_T("系统提示"),MB_ICONQUESTION|MB_OKCANCEL)) { DestroyWindow(hWnd); } case WM_TIMER: RECT mRect; mRect.top=4*26 4; mRect.left=0; mRect.right=m_Rect.right; mRect.bottom=5*26 4; ::InvalidateRect(hWnd,&mRect,FALSE); break; case WM_DESTROY: FreeParams(); PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Mesage handler for about box. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } //初始化系统参数 void InitParams(void) { m_Rect.top=0; m_Rect.bottom=400; m_Rect.left=0; m_Rect.right=600; m_CountInfo.nCientNum=0; m_CountInfo.nRcvPagesNum=0; m_CountInfo.nRcvThreadNum=0; m_CountInfo.nRcvBytesSize=0; m_CountInfo.nRcvAllBytesSize=0; m_ServerState.lHeartNum=0; m_ServerState.bServerState=FALSE; m_ServerState.lRecvNum=0; m_bShowClient=FALSE; m_bDrawClient=TRUE; m_nPageIndex=0; StartServer(); SetTimer(m_hWnd,MTIMER_ID,1000,NULL); } //结束时释放 void FreeParams(void) { StopServer(); m_ClientMap.clear(); } //界面上绘制信息 void DrawInfo(HDC hDC) { RECT mRect; ::GetClientRect(m_hWnd,&mRect); HDC hMemDC=::CreateCompatibleDC(hDC); HBITMAP hBitMap=::CreateCompatibleBitmap(hDC,mRect.right,mRect.bottom); HBITMAP hOldBitMap=(HBITMAP)::SelectObject(hMemDC,hBitMap); ::SetTextColor(hMemDC,RGB(192,192,192)); ::SetBkColor(hMemDC,RGB(0,0,0)); //::Rectangle(hMemDC,0,0,mRect.right,mRect.bottom); POINT mPoint; HPEN hPen=::CreatePen(PS_DOT,1,RGB(100,100,100)); HPEN hOldPen=(HPEN)::SelectObject(hMemDC,hPen); for(int nY=26;nY<=mRect.bottom;nY =26) { ::MoveToEx(hMemDC,1,nY,&mPoint); ::LineTo(hMemDC,mRect.right-1,nY); } ::SelectObject(hMemDC,hOldPen); ::DeleteObject(hPen); char chMsg[100]=""; mRect.left=2; mRect.top=4; sprintf(chMsg,"Server State : %s",m_ServerState.bServerState?"Success(TCP)":"Falied(TCP)"); ::DrawText(hMemDC, chMsg, strlen(chMsg), &mRect, DT_LEFT); mRect.top=1*26 4; // map<int,Client_Info>::iterator iter; int iOnlineClientSize=0; for(iter=m_ClientMap.begin();iter!=m_ClientMap.end();iter ) { if(((Client_Info)iter->second).bState) { iOnlineClientSize ; } else { //m_ClientMap.erase(iter); } } // sprintf(chMsg,"Online Clients Num : %d (Click Me,Look All Client's Info)",iOnlineClientSize); ::DrawText(hMemDC, chMsg, strlen(chMsg), &mRect, DT_LEFT); mRect.top=2*26 4; sprintf(chMsg,"Client Heart Jump Num : %d",m_ServerState.lHeartNum); ::DrawText(hMemDC, chMsg, strlen(chMsg), &mRect, DT_LEFT); mRect.top=3*26 4; sprintf(chMsg,"Receive Data Page Num : %d",m_ServerState.lRecvNum); ::DrawText(hMemDC, chMsg, strlen(chMsg), &mRect, DT_LEFT); SYSTEMTIME mSYSTEMTIME; ::GetSystemTime(&mSYSTEMTIME); mRect.top=4*26 4; sprintf(chMsg,"Server Datetime : %d-%d-%d %d:%d:%d DayOfWeek : %d",mSYSTEMTIME.wYear,mSYSTEMTIME.wMonth,mSYSTEMTIME.wDay,mSYSTEMTIME.wHour 8,mSYSTEMTIME.wMinute,mSYSTEMTIME.wSecond,mSYSTEMTIME.wDayOfWeek); ::DrawText(hMemDC, chMsg, strlen(chMsg), &mRect, DT_LEFT); if(m_bShowClient) { HBRUSH hBru=::CreateSolidBrush(RGB(253,251,183)); HBRUSH hOldBru=(HBRUSH)::SelectObject(hMemDC,hBru); ::Rectangle(hMemDC,0,52,m_Rect.right,m_Rect.bottom); ::SelectObject(hMemDC,hOldBru); ::DeleteObject(hBru); //map<int,Client_Info>::iterator iter; RECT mNetInfoRect; mNetInfoRect.left=2; mNetInfoRect.top=52; mNetInfoRect.right=m_Rect.right; mNetInfoRect.bottom=m_Rect.bottom; SetBkMode(hMemDC,TRANSPARENT); //SetTextColor(hMemDC,RGB(0,0,0)); if(m_bDrawClient) { int iIndex=0; int iTmpIndex=0; for(iIndex=0,iter=m_ClientMap.begin();iter!=m_ClientMap.end();iter ) { if(iTmpIndex<m_nPageIndex*48) { iTmpIndex ; continue; } if(((Client_Info)iter->second).bState) { ::SetTextColor(hMemDC,RGB(0,0,255)); /*if(iIndex<16) { mNetInfoRect.top=iIndex*18 52; mNetInfoRect.left=2; } if(iIndex<32 && iIndex>=16) { mNetInfoRect.top=(iIndex%16)*18 52; mNetInfoRect.left=200; } if(iIndex<48 && iIndex>=32) { mNetInfoRect.top=(iIndex%32)*18 52; mNetInfoRect.left=400; } if(iIndex<48) { Client_Info mClientInfo= (Client_Info)iter->second; sprintf(chMsg,"NetAdress: %s:%d",inet_ntoa(mClientInfo.mSOCKADDR_IN.sin_addr),mClientInfo.mSOCKADDR_IN.sin_port); ::DrawText(hMemDC, chMsg, strlen(chMsg), &mNetInfoRect, DT_LEFT); } iIndex ;*/ } else { ::SetTextColor(hMemDC,RGB(255,0,0)); } if(iIndex<16) { mNetInfoRect.top=iIndex*18 52; mNetInfoRect.left=2; } if(iIndex<32 && iIndex>=16) { mNetInfoRect.top=(iIndex%16)*18 52; mNetInfoRect.left=200; } if(iIndex<48 && iIndex>=32) { mNetInfoRect.top=(iIndex%32)*18 52; mNetInfoRect.left=400; } if(iIndex<48) { Client_Info mClientInfo= (Client_Info)iter->second; sprintf(chMsg,"NetAdress: %s:%d",inet_ntoa(mClientInfo.mSOCKADDR_IN.sin_addr),mClientInfo.mSOCKADDR_IN.sin_port); ::DrawText(hMemDC, chMsg, strlen(chMsg), &mNetInfoRect, DT_LEFT); } iIndex ; } ::SetTextColor(hMemDC,RGB(0,0,0)); ::SetBkMode(hMemDC,OPAQUE); ::SetBkColor(hMemDC,RGB(200,200,200)); RECT mRectOpt; mRectOpt.left=mNetInfoRect.right-80; mRectOpt.top=mNetInfoRect.bottom-62; mRectOpt.right=mNetInfoRect.right; mRectOpt.bottom=mNetInfoRect.bottom; ::DrawText(hMemDC, "[最后一页]", 10, &mRectOpt, DT_LEFT); mRectOpt.left=mRectOpt.left-64; ::DrawText(hMemDC, "[上一页]", 8, &mRectOpt, DT_LEFT); mRectOpt.left=mRectOpt.left-64; if(0==m_ClientMap.size()) { sprintf(chMsg,"%d/%d",0,0); } else { int nPageCount=0; if(0==m_ClientMap.size()%48) { nPageCount=m_ClientMap.size()/48; } else { nPageCount=m_ClientMap.size()/48 1; } sprintf(chMsg,"%d/%d",m_nPageIndex 1,nPageCount); } ::DrawText(hMemDC, chMsg, strlen(chMsg), &mRectOpt, DT_LEFT); mRectOpt.left=mRectOpt.left-90; ::DrawText(hMemDC, "[下一页]", 8, &mRectOpt, DT_LEFT); mRectOpt.left=mRectOpt.left-64; ::DrawText(hMemDC, "[第一页]", 8, &mRectOpt, DT_LEFT); } } ::BitBlt(hDC,0,0,mRect.right,mRect.bottom,hMemDC,0,0,SRCCOPY); ::SelectObject(hMemDC,hOldBitMap); ::DeleteObject(hBitMap); ::DeleteDC(hMemDC); } //处理接收信息 void ParseMsg(SOCKET mSendSocket,char* mCh,int nRcvLen) { if(('&'==mCh[0] && '^'==mCh[6]) || (nRcvLen<10 && '^'==mCh[nRcvLen-1])) { //&c0001^ 心跳 m_ServerState.lHeartNum ; //send(mSendSocket,"&s0001^",7,0); } else { m_ServerState.lRecvNum ; map<int,Client_Info>::iterator iter; for(iter=m_ClientMap.begin();iter!=m_ClientMap.end();iter ) { Client_Info mClientInfo= (Client_Info)iter->second; if(mSendSocket!=mClientInfo.mSOCKET && mClientInfo.bState) { send(mClientInfo.mSOCKET,mCh,nRcvLen,0);// } } } }
好例子网口号:伸出你的我的手 — 分享!
相关软件
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论