本文介绍了在Windows 操作系统下基于TCP/IP 协议Socket 套接口的通信机制以及多线程编程知识与技巧,并给出多线程方式实现多用户与服务端(C/S)并发通信模型的详细算法,最后展现了用C++编写的多用户与服务器通信的应用实例并附有程序。
关键词:Windows;套接字;多线程;并发服务器;
Socket 是建立在传输层协议(主要是TCP 和UDP)上的一种套接字规范,最初由美国加州Berkley 大学提出,为UNIX 系统开发的网络通信接口,它定义了两台计算机之间通信的规范,socket 屏蔽了底层通信软件和具体操作系统的差异,使得任何两台安装了TCP 协议软件和实现了Socket 规范的计算机之间的通信成为可能,Socket 接口是TCP/IP 网络最为通用的应用接口,也是在Internet 上进行网络程序应用开发最通用的API[1],本文介绍了Socket通信的基本机制以及采用多线程技术实现并发通信的基本原理,并给出实例。
全部代码详见:http://download.csdn.net/detail/xy010902100449/8570623
//----------------------------------------------------------------------------------- // 版权归scut4009所有 //----------------------------------------------------------------------------------- // 文件名:SocketSever.cpp // 编写人:ZP1015 // 编写时间:2015/04/7 // 编译工具: Visual Studio 2008 // 程序说明: socket多线程通信,服务器端,基于TCP //------------------------------------------------------------------------------------ #include "stdafx.h" #include "Socket.h" #include<windows.h> HANDLE hMutex; //------------------------------------------------------------------------------------ //函数名称: Send(SOCKET sockClient) /*函数功能: 发送数据 /*入口参数: SOCKET sockClient //出口参数: //全局变量引用: //调用模块: 无 //------------------------------------------------------------------------------------*/ void Send(SOCKET sockClient) { char sendBuf[MaxSize]; int byte = 0; while(1) { WaitForSingleObject(hMutex, INFINITE); gets(sendBuf); byte= send(sockClient,sendBuf,strlen(sendBuf)+1,0);;//服务器从客户端接受数据 if (byte<=0) { break; } Sleep(1000); ReleaseMutex(hMutex); } closesocket(sockClient);//关闭socket,一次通信完毕 } //------------------------------------------------------------------------------------ //函数名称: Rec() /*函数功能: 接收函数 /*入口参数: SOCKET sockClient //出口参数: //全局变量引用: //调用模块: 无 //------------------------------------------------------------------------------------*/ void Rec(SOCKET sockClient) { char revBuf[MaxSize]; int byte = 0; while(1) { WaitForSingleObject(hMutex, INFINITE); byte= recv(sockClient,revBuf,strlen(revBuf)+1,0);//服务器从客户端接受数据 if (byte<=0) { break; } printf("%s\n",revBuf); Sleep(1000); ReleaseMutex(hMutex); } closesocket(sockClient);//关闭socket,一次通信完毕 } //********************************************************************************************************/ //** 函数名 ** main() //** 输入 ** 无 //** 输出 ** 无 //**函数描述** 主函数 //********************************************************************************************************/ int main() { SOCKADDR_IN addrServer; int sockServer; if (SOCKET_ERROR ==SocketInit()) { return -1; } addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY); //htol将主机字节序long型转换为网络字节序 addrServer.sin_family=AF_INET; addrServer.sin_port=htons(6666); //htos用来将端口转换成字符,1024以上的数字即可 sockServer=socket(AF_INET,SOCK_STREAM,0); //面向连接的可靠性服务SOCK_STRAM bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));//将socket绑定到相应地址和端口上 listen(sockServer,5); //等待队列中的最大长度为5 printf("Welcome,the Host %s is running!Now Wating for someone comes in!\n",inet_ntoa(addrServer.sin_addr)); int len=sizeof(SOCKADDR); SOCKADDR_IN addrClient; while(1) { SOCKET sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len);//阻塞调用进程直至新的连接出现 if(sockClient == INVALID_SOCKET) { printf("Accept Failed!\n"); continue; //继续监听 } HANDLE hThread1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Send,(LPVOID)sockClient,0,0);//发送 if(hThread1!=NULL) { CloseHandle(hThread1); } HANDLE hThread2 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Rec,(LPVOID)sockClient,0,0);//接收 if(hThread2!=NULL) { CloseHandle(hThread2); } Sleep(1000); //一定要 } getchar(); return 0; }
//----------------------------------------------------------------------------------- // 版权归scut4009所有 //----------------------------------------------------------------------------------- // 文件名:SocketClient.cpp // 编写人:ZP1015 // 编写时间:2015/04/7 // 编译工具: Visual Studio 2008 // 程序说明: socket多线程通信 //------------------------------------------------------------------------------------ #include "stdafx.h" #include "Socket.h" #pragma comment(lib,"WS2_32.LIB") const char *SeverIp = "192.168.1.100"; HANDLE hMutex; //------------------------------------------------------------------------------------ //函数名称: Send(SOCKET sockClient) /*函数功能: 发送数据 /*入口参数: SOCKET sockClient //出口参数: //全局变量引用: //调用模块: 无 //------------------------------------------------------------------------------------*/ void Send(SOCKET sockClient) { char sendBuf[MaxSize]; int byte = 0; while(1) { WaitForSingleObject(hMutex, INFINITE); gets(sendBuf); byte= send(sockClient,sendBuf,strlen(sendBuf)+1,0);;//服务器从客户端接受数据 if (byte<=0) { break; } Sleep(1000); ReleaseMutex(hMutex); } closesocket(sockClient);//关闭socket,一次通信完毕 } //------------------------------------------------------------------------------------ //函数名称: Rec() /*函数功能: 接收函数 /*入口参数: SOCKET sockClient //出口参数: //全局变量引用: //调用模块: 无 //------------------------------------------------------------------------------------*/ void Rec(SOCKET sockClient) { char revBuf[MaxSize]; int byte = 0; while(1) { WaitForSingleObject(hMutex, INFINITE); byte= recv(sockClient,revBuf,strlen(revBuf)+1,0);//服务器从客户端接受数据 if (byte<=0) { break; } printf("%s\n",revBuf); Sleep(1000); ReleaseMutex(hMutex); } closesocket(sockClient);//关闭socket,一次通信完毕 } int main() { if (SOCKET_ERROR ==SocketInit()) { return -1; } while(1) { SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=inet_addr(SeverIp);//设定需要连接的服务器的ip地址 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6666);//设定需要连接的服务器的端口地址 connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//与服务器进行连接 HANDLE hThread1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Rec,(LPVOID)sockClient,0,0); if(hThread1!=NULL) { CloseHandle(hThread1); } HANDLE hThread2 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Send,(LPVOID)sockClient,0,0); if(hThread2!=NULL) { CloseHandle(hThread2); } Sleep(1000); } getchar(); WSACleanup(); return -1; }
原文地址:http://blog.csdn.net/xy010902100449/article/details/44920407