基于WinSocket的单线程Server的实现

来源:互联网 发布:用友js面试题 编辑:程序博客网 时间:2024/04/26 04:20
基于WinSocket的单线程Server的实现
功能描述:
程序实现一个Server监听端口的功能,运行后,其处于监听状态。当有Client连接到此Server,它停止监听,接收到自此client的数据,并将从Client收到数据反射给Client。
 
调用顺序:
1.         WSAStartup:开始对WS2_32.dll的使用。
2.         socket:创建一个socket。
3.         bind:绑定IP与Port。
4.         listen:监听一个socket。
5.         accept:接受client的连接。
6.         send:向指定socket发送数据。
7.         recv:从指定的socket接收数据。
8.         WSACleanup:关闭对WS2_32.dll的使用。
函数说明;
int WSAStartup(
 WORD wVersionRequested,
 LPWSADATA wVersionRequested,
 LPWSADATA lpWSAData
);
功能:启动WS2_32.dll,将将获得的Winsocket实现的详细信息保存到lpMSAData所指向的数据结构中,调用此函数后才可以使用Winsocket相关的函数。

     //Initialize a WSADATA object
     WSADATA wsaData;
     int nResult = WSAStartup(MAKEWORD(2,2),&wsaData);
 

 
SOCKET socket(
 int af,
 int af,
 int type,
 int protocol
);
功能:创建一个绑定到指定service provider上的socket。

     //Create a socket
     SOCKET m_socket;
     m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 

 
int bind(
 SOCKET s,
 const struct sockaddr* s,
 const struct sockaddr* name,
 int namelen
);
功能:将本地地址与一个socket绑定。

     //Bind a socket
     sockaddr_in service;
     service.sin_family = AF_INET;
     service.sin_addr.s_addr = inet_addr("127.0.0.1");
     service.sin_port = htons(27002);
 
     if(bind(m_socket,(SOCKADDR*)&service,sizeof(service)) == SOCKET_ERROR){
         cout << "Error at bind " << endl;
         closesocket(m_socket);
         return 1;
     }

int listen(
 SOCKET s,
 int s,
 int backlog
);
功能:将一个socket置于监听状态。

     //listen on a socket
     if(listen(m_socket,20) == SOCKET_ERROR){
         cout << "Error on listen" << endl;
         return 1;
     }

SOCKET accept(
 SOCKET s,
 struct sockaddr* s,
 struct sockaddr* addr,
 int* addrlen
);
功能:接受来自外部的Client连接,返回一个新的socket。

         AcceptSocket = SOCKET_ERROR;
         while (AcceptSocket == SOCKET_ERROR) {
              AcceptSocket = accept(m_socket,NULL,NULL);
         }

 
int recv(
 SOCKET s,
 char* s,
 char* buf,
 int len,
 int len,
 int flags
);
功能:从指定的socket中接收数据。

     int nSendBytes = 0;
     int nRecvBytes = 0;
     char pRecvBytes[32] = "";
 
     nRecvBytes = recv(m_socket,pRecvBytes,32,0);
     cout << "Num of receive :" << nRecvBytes << endl;
     cout << pRecvBytes << endl;

 
int send(
 SOCKET s,
 const char* s,
 const char* buf,
 int len,
 int len,
 int flags
);
功能:向已连接的socket发送数据。

     char pSendBytes[32] = "Server:Send data";
     nSendBytes = send(m_socket,pSendBytes,32,0);

 
int WSACleanup(void);
功能:关闭能WS2_32.dll的使用,调用次数应该与WSAStartup相同。

     WSACleanup();

 
完整代码

#include <iostream>
#include "winsock2.h"
#include <windows.h>
 
using namespace std;
 
int main(){
     //启动WS2_32.dll
     WSADATA wsaData;
     int nResult = WSAStartup(MAKEWORD(2,2),&wsaData);
     if(nResult != NO_ERROR){
         cout << "Error at WSAStartup" << endl;
         return 1;
     }
 
     //创建一个socket
     SOCKET m_socket;
     m_socket = socket(AF_INET, //协议族
         SOCK_STREAM,           //SOCKET类型
         IPPROTO_TCP);          //此socket使用的协议
     if(m_socket == INVALID_SOCKET){
         cout << "Error at socket " << WSAGetLastError() << endl;
         WSACleanup();
         return 1;
     }
 
     //Bind a socket
     sockaddr_in service;
     service.sin_family = AF_INET;//协议族
     service.sin_addr.s_addr = inet_addr("127.0.0.1");//IP地址
     service.sin_port = htons(27002);               //端口号
 
     //将socket与指定的地址绑定
     if(bind(m_socket,(SOCKADDR*)&service,sizeof(service)) == SOCKET_ERROR){
         cout << "Error at bind " << endl;
         closesocket(m_socket);
         return 1;
     }
 
     //监听socket
     if(listen(m_socket,20) == SOCKET_ERROR){
         cout << "Error on listen" << endl;
          return 1;
     }
 
     //接受一个socket连接
     SOCKET AcceptSocket;
     cout << "Waiting for client to connect" << endl;
     while (1) {
         AcceptSocket = SOCKET_ERROR;
         while (AcceptSocket == SOCKET_ERROR) {
              AcceptSocket = accept(m_socket,NULL,NULL);
         }
 
         cout << "client connected!" << endl;
         m_socket = AcceptSocket;
         break;
     }
 
     int nSendBytes = 0;
     int nRecvBytes = 0;
     char pSendBytes[32] = "Server:Send data";
     char pRecvBytes[32] = "";
 
     //从socket接收数据.
     nRecvBytes = recv(m_socket,pRecvBytes,32,0);
     cout << "Num of receive :" << nRecvBytes << endl;
     cout << pRecvBytes << endl;
 
     //向socket发送数据。
     nSendBytes = send(m_socket,pSendBytes,32,0);
     if (nSendBytes == SOCKET_ERROR) {
         int nErr = WSAGetLastError();
         WSAEACCES;
         cout << nErr << endl;
     }else
        cout <<"Num of send : " << nSendBytes << endl;
     //清除WS2_32.dll
     Sleep(5000);
     WSACleanup();
   
     return 0;
}

 
原创粉丝点击