C---Socket网络通信实现一个服务器端和多个客户端的通信_第1页
C---Socket网络通信实现一个服务器端和多个客户端的通信_第2页
C---Socket网络通信实现一个服务器端和多个客户端的通信_第3页
C---Socket网络通信实现一个服务器端和多个客户端的通信_第4页
C---Socket网络通信实现一个服务器端和多个客户端的通信_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C+ Socket网络通信实现一个服务器端和多个客户端的通信 C+ Socket网络通信实现一个服务器端和多个客户端的通信标签: C+Socket但服务器对多客户端2017-04-06 10:59 499人阅读 评论(5) 收藏 举报 分类:C+网络通信(2) 版权声明:本文为博主原创文章,未经博主允许不得转载。一 描述1 采用C+语言2 编译环境是code:blocks3 使用的是非阻塞套接字二 功能描述1 一个服务器对多个客户端2 服务器端主要负责处理数据的输入并发送,具体是通过发送指令向其指定的客户端发送数据,发送接收指令读取其指定的客户端发送的数据3 客户端的主要负责接收并发送数据,不做数据的处理三 实现情况1 server 端2 client 端四 server思路图五 程序源码cpp view plain copy print?#include server.h #include <string.h> /定义全局变量 char dataBufMAX_NUM_BUF; /写缓冲区 BOOL bConning; /与客户端的连接状态 BOOL bSend ; /发送标记位 SOCKET sServer; /服务器监听套接字 CRITICAL_SECTION cs; /保护数据的临界区对象 HANDLE hAcceptThread; /数据处理线程句柄 HANDLE hRecvThread; /数据接收线程 ClIENTVECTOR clientvector; SVECTOR stringvector; /* * 初始化 */ BOOL InitSever(void) InitMember();/初始化全局变量 /初始化SOCKET if (!InitSocket() return FALSE; return TRUE; /* * 初始化全局变量 */ void InitMember(void) InitializeCriticalSection(&cs); /初始化临界区 memset(dataBuf, 0, MAX_NUM_BUF); bSend = FALSE; bConning = FALSE; /服务器为没有运行状态 hAcceptThread = NULL; /设置为NULL hRecvThread = NULL; sServer = INVALID_SOCKET; /设置为无效的套接字 clientvector.clear(); /清空向量 stringvector.clear(); /* * 初始化SOCKET */ bool InitSocket(void) /返回值 int reVal; /初始化Windows Sockets DLL WSADATA wsData; reVal = WSAStartup(MAKEWORD(2,2),&wsData); /创建套接字 sServer = socket(AF_INET, SOCK_STREAM, 0); if(INVALID_SOCKET= sServer) return FALSE; /设置套接字非阻塞模式 unsigned long ul = 1; reVal = ioctlsocket(sServer, FIONBIO, (unsigned long*)&ul); if (SOCKET_ERROR = reVal) return FALSE; /绑定套接字 sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(SERVERPORT); serAddr.sin_addr.S_un.S_addr = INADDR_ANY; reVal = bind(sServer, (struct sockaddr*)&serAddr, sizeof(serAddr); if(SOCKET_ERROR = reVal ) return FALSE; /监听 reVal = listen(sServer, SOMAXCONN); if(SOCKET_ERROR = reVal) return FALSE; /等待客户端的连接 cout << Server succeeded! << endl; cout << Waiting for clients. << endl; return TRUE; /* * 启动服务 */ bool StartService(void) BOOL reVal = TRUE; /返回值 ShowTipMsg(TRUE); /提示用户输入 char cInput; /输入字符 do cin >> cInput; if (s = cInput | S = cInput) if (createAcceptThread() /接受客户端请求的线程 ShowServerStartMsg(TRUE); /创建线程成功信息 else reVal = FALSE; bSend = TRUE; break;/跳出循环体 else ShowTipMsg(TRUE); while(cInput != s && cInput != S); /必须输入s或者S字符 return reVal; /* *des:create a client request thread */ BOOL createAcceptThread(void) bConning = TRUE;/设置服务器为运行状态 /创建释放资源线程 unsigned long ulThreadId; /创建接收客户端请求线程 hAcceptThread = CreateThread(NULL, 0, AcceptThread, NULL, 0, &ulThreadId); if( NULL = hAcceptThread) bConning = FALSE; return FALSE; else CloseHandle(hAcceptThread); return TRUE; /* * 接受客户端连接 */ DWORD _stdcall AcceptThread(void* pParam) SOCKET sAccept; /接受客户端连接的套接字 sockaddr_in addrClient; /客户端SOCKET地址 while(bConning) /服务器的状态 memset(&addrClient, 0, sizeof(sockaddr_in); /初始化 int lenClient = sizeof(sockaddr_in); /地址长度 sAccept = accept(sServer, (sockaddr*)&addrClient, &lenClient); /接受客户请求 if(INVALID_SOCKET = sAccept ) Sleep(100); int nErrCode = WSAGetLastError(); if(nErrCode = WSAEWOULDBLOCK) /无法立即完成一个非阻挡性套接字操作 Sleep(TIMEFOR_THREAD_SLEEP); continue;/继续等待 else return 0;/线程退出 else/接受客户端的请求 /显示客户端的IP和端口 char *pClientIP = inet_ntoa(addrClient.sin_addr); u_short clientPort = ntohs(addrClient.sin_port); cout<<Accept a client.<<endl; cout<<IP: <<pClientIP<<tPort: <<clientPort<<endl; /加入容器 clientvector.push_back(sAccept); return 0;/线程退出 /* *des:处理数据 */ void inAndOut(void) while(bConning) memset(dataBuf, 0, MAX_NUM_BUF); /清空接收缓冲区 cin.getline(dataBuf,MAX_NUM_BUF); /输入数据 /发送数据 if(bSend) handleData(dataBuf); /* *des:read a line words */ /* *读一行数据 */ bool RecvLine(SOCKET s, char* buf) bool retVal = TRUE; /返回值 bool bLineEnd = FALSE; /行结束 int nReadLen = 0; /读入字节数 int nDataLen = 0; /数据长度 memset(buf, 0, MAX_NUM_BUF); /清空接收缓冲区 while (!bLineEnd && bConning) /与客户端连接 没有换行 nReadLen = recv(s, buf + nDataLen, 1, 0); /每次接收一个字节 /错误处理 if(SOCKET_ERROR = nReadLen) int nErrCode = WSAGetLastError(); if ( WSAEWOULDBLOCK = nErrCode ) /接受数据缓冲区不可用 continue; /继续循环 else if(WSAENETDOWN = nErrCode | WSAETIMEDOUT = nErrCode | WSAECONNRESET = nErrCode) /客户端关闭了连接 retVal = FALSE; /读数据失败 break; /线程退出 if(0 = nReadLen) retVal = FALSE; break; if(n=*(buf + nDataLen) /读取结束 bLineEnd = TRUE; bSend = TRUE; /开始发送 else nDataLen += nReadLen; /增加数据长度 return retVal; /* * 读取数据 */ bool recvData(SOCKET s, char* buf) memset(buf, 0, MAX_NUM_BUF); /清空接收缓冲区 int nReadLen = 0; /读入字节数 bool bLineEnd = FALSE; /行结束 BOOL retVal = TRUE; while(!bLineEnd) nReadLen = recv(s, buf, MAX_NUM_BUF, 0); if(SOCKET_ERROR = nReadLen) int nErrCode = WSAGetLastError(); if ( WSAEWOULDBLOCK = nErrCode ) /接受数据缓冲区不可用 continue; /继续循环 else if(WSAENETDOWN = nErrCode | WSAETIMEDOUT = nErrCode | WSAECONNRESET = nErrCode) /客户端关闭了连接 retVal = FALSE; /读数据失败 break; /线程退出 if(0 = nReadLen) /未读取到数据 retVal = FALSE; break; bLineEnd = TRUE; return retVal; /* * Des:send data to client */ bool sendData(SOCKET s, char* str) int retVal; /返回值 bool bLineEnd = FALSE; /行结束 while(!bLineEnd) retVal = send(s, str, strlen(str), 0);/一次发送 /错误处理 if (SOCKET_ERROR = retVal) int nErrCode = WSAGetLastError();/错误代码 if (WSAEWOULDBLOCK = nErrCode) continue; else if(WSAENETDOWN = nErrCode | WSAETIMEDOUT = nErrCode | WSAECONNRESET = nErrCode) return FALSE; bLineEnd = TRUE; return TRUE; /发送成功 /* *des:handle data to choose what kind of pattern */ void handleData(char* str) SOCKET sClient; char cnum; /显示几号字套接字 int num; if(!strncmp(WRITE, str, strlen(WRITE) /判断输入指令是否为 str += strlen(WRITE); cnum = *str+; num = cnum - 1; /增加容量处理 sClient = clientvector.at(num); /发送到指定客户端 if(!sendData(sClient, str) ExitServer();/退出 else if(!strncmp(READ, str, strlen(READ) str += strlen(READ); cnum = *str+; num = cnum - 1; sClient = clientvector.at(num); /发送到指定客户端 /接收客户端数据 if (!recvData(sClient, dataBuf) ExitServer();/退出 /显示客户端数据 cout << dataBuf<<endl; else if(e=str0 | E= str0)&&(n = str1) /判断是否退出 bConning = FALSE; ExitServer(); ShowTipMsg(FALSE); else cout <<Input error!<<endl; /* * 释放资源 */ void ExitServer(void) closesocket(sServer); /关闭SOCKET WSACleanup(); /卸载Windows Sockets DLL void ShowTipMsg(BOOL bFirstInput) if (bFirstInput)/第一次 cout << endl; cout << endl; cout << * << endl; cout << * s(S): Start server * << endl; cout << * << endl; cout << Please input: ; else/退出服务器 cout << endl; cout << endl; cout << * << endl; cout << * e(E): Exit server * << endl; cout << * << endl; cout << Please input: ; /* * 显示启动服务器成功与失败消息 */ void ShowServerStartMsg(BOOL bSuc) if (bSuc) cout << * << endl; cout << * Server succeeded! * << endl; cout << * << endl; else cout << * << endl; cout << * Server failed ! * << endl; cout << * << endl; cpp view plain copy print?#include client.h /变量 SOCKET sClient; /套接字 char dataBufMAX_NUM_BUF; /数据缓冲区 BOOL bSend = FALSE; /发送标记位 BOOL bConnecting; /与服务器的连接状态 /* * 初始化 */ BOOL InitClient(void) /初始化全局变量 InitMember(); /创建SOCKET if (!InitSockt() return FALSE; return TRUE; /* * 初始化全局变量 */ void InitMember(void) / InitializeCriticalSection(&cs); sClient = INVALID_SOCKET; /套接字 / handleThread = NULL; /接收数据线程句柄 bConnecting = FALSE; /为连接状态 / /初始化数据缓冲区 / memset(dataBuf, 0, MAX_NUM_BUF); /* * 创建非阻塞套接字 */ BOOL InitSockt(void) int reVal; /返回值 WSADATA wsData; /WSADATA变量 reVal = WSAStartup(MAKEWORD(2,2),&wsData);/初始化Windows Sockets Dll /创建套接字 sClient = socket(AF_INET, SOCK_STREAM, 0); if(INVALID_SOCKET = sClient) return FALSE; /设置套接字非阻塞模式 unsigned long ul = 1; reVal = ioctlsocket(sClient, FIONBIO, (unsigned long*)&ul); if (reVal = SOCKET_ERROR) return FALSE; return TRUE; /* * 连接服务器 */ BOOL ConnectServer(void) int reVal; /返回值 sockaddr_in serAddr;/服务器地址 /输入要连接的主机地址 serAddr.sin_family = AF_INET; serAddr.sin_port = htons(SERVERPORT); serAddr.sin_addr.S_un.S_addr = inet_addr(SERVERIP); while(true) /连接服务器 reVal = connect(sClient, (struct sockaddr*)&serAddr, sizeof(serAddr); /处理连接错误 if(SOCKET_ERROR = reVal) int nErrCode = WSAGetLastError(); if( WSAEWOULDBLOCK = nErrCode | WSAEINVAL = nErrCode) /连接还没有完成 continue; else if (WSAEISCONN = nErrCode)/连接已经完成 break; else/其它原因,连接失败 return FALSE; if ( reVal = 0 )/连接成功 break; bConnecting = TRUE; return TRUE; /* *des:recvive and send data */ void recvAndSend(void) while(bConnecting) /接收客户端数据 if (!recvData(sClient, dataBuf) ExitClient();/退出 /显示客户端数据 cout << dataBuf<<endl; /向客户端发送数据 if(!sendData(sClient, dataBuf) ExitClient();/退出 /* *des:read a line words */ /* *读一行数据 */ bool RecvLine(SOCKET s, char* buf) bool retVal = TRUE; /返回值 bool bLineEnd = FALSE; /行结束 int nReadLen = 0; /读入字节数 int nDataLen = 0; /数据长度 memset(buf, 0, MAX_NUM_BUF); /清空接收缓冲区 while (!bLineEnd && bConnecting) /与客户端连接 没有换行 nReadLen = recv(s, buf + nDataLen, 1, 0); /每次接收一个字节 /错误处理 if(SOCKET_ERROR = nReadLen) int nErrCode = WSAGetLastError(); if ( WSAEWOULDBLOCK = nErrCode ) /接受数据缓冲区不可用 continue; /继续循环 else if(WSAENETDOWN = nErrCode | WSAETIMEDOUT = nErrCode | WSAECONNRESET = nErrCode) /客户端关闭了连接 retVal = FALSE; /读数据失败 break; /线程退出 if(0 = nReadLen) retVal = FALSE; break; if(s=buf0 | S=buf0)&&(n = buf1) /判断是否退出 bConnecting = FALSE; bSend = FALSE; memset(buf, 0, MAX_NUM_BUF); /清空接收缓冲区 ShowConnectMsg(FALSE); if(n=*(buf + nDataLen) /读取结束 bLineEnd = TRUE; bSend = TRUE; /开始发送 else nDataLen += nReadLen; /增加数据长度 return retVal; /* * 读取数据 */ bool recvData(SOCKET s, char* buf) BOOL retVal = TRUE; bool bLineEnd = FALSE; /行结束 memset(buf, 0, MAX_NUM_BUF); /清空接收缓冲区 int nReadLen = 0; /读入字节数 while(!bLineEnd) nReadLen = recv(s, buf, MAX_NUM_BUF, 0); if(SOCKET_ERROR = nReadLen) int nErrCode = WSAGetLastError(); if ( WSAEWOULDBLOCK = nErrCode ) /接受数据缓冲区不可用 continue; /继续循环 else if(WSAENETDOWN

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论