基于控制台的简单网络编程代码。
服务器代码:
// Sever.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <WinSock2.h> #pragma comment(lib,"Ws2_32.lib") int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsadata; //第一个参数指明程序请求的Socket版本,第二个参数指向WSADATA数据结构的指针,用来接受windows sockets实现的细节 //当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中 //以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。 //一旦应用程序或者DLL进行了一次成功的WSAStartup()调用,它就可以继续进行其它所需的windows Socket API调用。当它完成了使用 //该Windows Socket DLL的服务后,应用程序或DLL必须调用WSAClearup()以允许Windows Socket DLL释放任何该应用程序的资源。 WSAStartup(0x0202,&wsadata); //第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置AF_INET //第二个参数指定要创建的套接字类型,流套接字类型为SOCKT_STREAM //第三个参数指定应用程序所使用的通信协议。此参数可以指定单个协议系列中的不同传输协议。在internet通讯域中, //此参数一般取值为0,系统会根据套接字的类型决定使用的传输层协议 SOCKET ListenSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //struct sockaddr是一个通用地址结构,这是为了统一地址结构的表示方法,统一接口函数,使不同的地址结构可以被bind(),connect()等函数 //调用;struct sockaddr_in 中的in表示internet,就是网络地址。 sockaddr_in ListenAddr; memset(&ListenAddr,0,sizeof(sockaddr_in)); //sin_family指代协议族,在socket编程中只能是AF_INET ListenAddr.sin_family=AF_INET; //sin_port存储端口号 ListenAddr.sin_port=htons(7070); //sin_addr存储IP地址,使用in_addr这个数据结构 ListenAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); //bind函数用于将套接字绑定到一个已知的地址上 //函数原型int bind(SCOKET socket,const struct sockaddr* address,socklen_t address_len); bind(ListenSocket,(sockaddr *)&ListenAddr,sizeof(sockaddr)); //listen函数使主动链接套接口变为被连接套接口,使得一个进程可以接受其它进程的请求,从而成为一个服务器进程。 //在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接 listen(ListenSocket,5); SOCKET ClientSocket=0; sockaddr_in ClientAddr; int ClientAddrLeng; printf("服务器启动成功!\n"); REACCEPT: ClientSocket=0; ClientAddrLeng=sizeof(sockaddr_in); memset(&ClientAddr,0,sizeof(sockaddr_in)); //对于服务器编程中最重要的一步等待并接受客户的连接,那么这一步在编程中如何完成,accept函数就是完成这一步的。 //它从内核中取出已经建立的客户连接,然后把这个已经建立的连接返回给用户程序,此时用户程序就可以与自己的客户进行点到点的通信了 ClientSocket=accept(ListenSocket,(sockaddr *)&ClientAddr,&ClientAddrLeng); if(ClientSocket==INVALID_SOCKET) { printf("客户接连失败,尝试再试连接!\n"); closesocket(ClientSocket); goto REACCEPT; } else { printf("[%d]客户接连成功!\n",ClientSocket); } char Buffer[999]; int RecvNum=0; while(1) { //不论是客户端还是服务器应用程序都用recv函数来向TCP连接的另一端接收数据 //第一个参数指定接受另一端套接字描述符 //第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接受到的数据 //第三个参数指明buf的长度 //第四个参数一般置为0 RecvNum=recv(ClientSocket,Buffer,999,0); if((RecvNum==0)||(RecvNum==SOCKET_ERROR)) { printf("[%d]客户断开连接或异常中断!\n",ClientSocket); break; } else { printf("%s\n",Buffer); //不论是客户端还是服务器应用程序都用send函数来向TCP连接的另一端发送数据 //客户端程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答 send(ClientSocket,Buffer,RecvNum,0); } } closesocket(ClientSocket); closesocket(ListenSocket); WSACleanup(); return 0; }
// Cllient.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <WinSock2.h> #pragma comment(lib,"Ws2_32.lib") int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsadata; WSAStartup(0x0202,&wsadata); SOCKET SeverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); sockaddr_in SeverAddr; memset(&SeverAddr,0,sizeof(sockaddr_in)); SeverAddr.sin_family=AF_INET; SeverAddr.sin_port=htons(7070); SeverAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); int r=connect(SeverSocket,(sockaddr *)&SeverAddr,sizeof(sockaddr)); if(r==0) { printf("连接服务器成功!\n"); } else { printf("连接服务器失败!\n"); goto EXIT; } char Buffer[999]; int RecvNum=0; while(1) { scanf("%s",Buffer); if(strcmp(Buffer,"x")==0) { break; } send(SeverSocket,Buffer,strlen(Buffer)+1,0); RecvNum=recv(SeverSocket,Buffer,999,0); if((RecvNum==0)||(RecvNum==SOCKET_ERROR)) { printf("服务器断开连接或连接异常断开\n"); break; } else { printf("%s\n",Buffer); } } EXIT: closesocket(SeverSocket); WSACleanup(); getchar(); return 0; }