zoukankan      html  css  js  c++  java
  • Winsock编程原理——面向连接

    Winsock编程原理——面向连接

    Windows Sockets使用套接字进行编程,套接字编程是面向客户端/服务器模型而设计的,因此系统中需要客户端和服务器两个不同类型的进程,根据连接类型的不同,对于面向连接的TCP服务和无连接的UDP服务,服务器分别采取不同的处理操作来对客户提供服务。

    面向连接

    服务器
    socket() -> bind() -> listen() -> accept() -> recv()/send() -> closesocket();
    创建套接字,绑定IP和端口,侦听,接收连接,收发消息,关闭连接
    客户端
    socket() -> connet() -> send()/recv() -> closesocket();
    创建套接字,连接服务器,发收消息,关闭连接
     
    一对一的模式,一个服务器, 一个客户端
     
     1 /*
     2 服务器端代码
     3 */
     4 
     5 #include<Winsock2.h>
     6 #include<stdio.h>
     7 #include<stdlib.h>
     8 #pragma comment(lib,"ws2_32.lib")
     9 #define PORT 5000
    10 
    11 void main()
    12 {
    13     int port = PORT;                                    //端口
    14     WSADATA wsaData;                                    //存储系统传回的关于Winsock的资料
    15     SOCKET sListen, sAccept;                            //套接字
    16     int iLen;                                            //客户地址长度
    17     int iSend;                                            //发送数据长度
    18     char buf[] = "Hello, How are you!";                    //需要发送的信息
    19     struct sockaddr_in serv, cliet;                        //服务器、客户的地址
    20 
    21     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)        //函数WSAStartup用以打开Winsock
    22     {
    23         printf("Winsock load failed
    ");
    24         return;
    25     }
    26 
    27     sListen = socket(AF_INET, SOCK_STREAM, 0);            //创建套接字,TCP协议
    28     if (sListen == INVALID_SOCKET)                        //socket调用成功返回套接字对象,失败返回INVALID_SOCKET
    29     {
    30         printf("socket failed:%d
    ", WSAGetLastError());
    31         return;
    32     }
    33 
    34     serv.sin_family = AF_INET;                            //网络中标识不同设备使用的地址类型,对于IP地址,类型是AF_INET
    35     serv.sin_port = htons(port);                        //socket对应的端口号
    36     serv.sin_addr.s_addr = htonl(INADDR_ANY);            //封装了IP地址
    37     if (bind(sListen, (LPSOCKADDR)&serv, sizeof(serv)) == SOCKET_ERROR)        //绑定套接字
    38     {
    39         printf("bind() failed:%d
    ", WSAGetLastError());
    40         return;
    41     }
    42 
    43     if (listen(sListen, 5) == SOCKET_ERROR)                //监听
    44     {
    45         printf("listen() failed:%d
    ", WSAGetLastError());
    46         return;
    47     }
    48 
    49     iLen = sizeof(cliet);                                //初始化客户地址长度
    50 
    51     while (1)                                            //进入循环,等待客户连接请求
    52     {
    53         sAccept = accept(sListen, (struct sockaddr*)&cliet, &iLen);    //客户端的套接字
    54         if (sAccept == INVALID_SOCKET)                    //接受连接请求失败
    55         {
    56             printf("accept() failed:%d
    ", WSAGetLastError());
    57             break;
    58         }
    59         //输出客户端IP、端口
    60         printf("accept() client IP:[%s], port:[%d]
    ", inet_ntoa(cliet.sin_addr), ntohs(cliet.sin_port));
    61 
    62         //给连接的客户发送消息
    63         iSend = send(sAccept, buf, sizeof(buf), 0);
    64         if (iSend == SOCKET_ERROR)
    65         {
    66             printf("send() failed:%d
    ", WSAGetLastError());
    67             break;
    68         }
    69         else if (iSend == 0)
    70             break;
    71         else
    72             printf("send() byte:%d
    ", send);
    73 
    74         closesocket(sListen);                            //关闭套接字
    75         closesocket(sAccept);                            //关闭套接字
    76         WSACleanup();                                    //关闭Winsock
    77     }
    78     while (1);
    79 }
    server
     1 /*
     2 客户端程序
     3 */
     4 #include<WinSock2.h>
     5 #include<stdio.h>
     6 #pragma comment(lib,"ws2_32.lib")
     7 #define PORT 5000
     8 #define BUFFER 1024
     9 
    10 void main(int argc,char *argv[])
    11 {
    12     WSADATA wsaData;
    13     SOCKET client;
    14     int port = PORT;
    15     int iLen;                                                //从服务器接收的数据长度
    16     char buf[BUFFER];                                        //接收数据的缓冲
    17     struct sockaddr_in serv;                                //服务器端地址
    18     memset(buf, 0, sizeof(buf));                            //接受数据缓冲区初始化
    19 
    20     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)            //函数WSAStartup用以打开Winsock
    21     {
    22         printf("Winsock load failed
    ");
    23         return;
    24     }
    25 
    26     serv.sin_family = AF_INET;                                //需要连接服务器地址信息,AF_INET表示IP协议
    27     serv.sin_port = htons(port);                            //端口
    28 //    serv.sin_addr.s_addr = inet_addr(argv[1]);                //IP地址,转为二进制表示的字节IP地址,argv表示cmd下输入的参数
    29     serv.sin_addr.s_addr = inet_addr("10.100.211.224");
    30     client = socket(AF_INET, SOCK_STREAM, 0);                //客户端套接字,流套接字表示使用TCP协议
    31     if (client == INVALID_SOCKET)                            //创建套接字失败
    32     {
    33         printf("socket() failed:%d
    ", WSAGetLastError());
    34         return;
    35     }
    36 
    37     //连接服务器
    38     if (connect(client, (struct sockaddr*)&serv, sizeof(serv)) == INVALID_SOCKET)    
    39     {
    40         printf("connet() failed:%d
    ", WSAGetLastError);
    41         return;
    42     }
    43     else
    44     {
    45         iLen = recv(client, buf, sizeof(buf), 0);            //从服务器接收数据
    46         if (iLen = 0)
    47             return;
    48         else if (iLen == SOCKET_ERROR)
    49         {
    50             printf("recv() failed:%d
    ", WSAGetLastError());
    51             return;
    52         }
    53         printf("recv() data from server:%s
    ", buf);
    54     }
    55 
    56     closesocket(client);                                    //关闭套接字
    57     WSACleanup;                                                //关闭Winsock
    58 
    59 //    system("pause");    //程序暂停
    60     printf("press any key to continue");                    //让程序等待
    61     while (1);
    62 }
    client

    加入多线程机制,一个服务器,多个客户端  

      1 /*
      2 服务器端代码
      3 */
      4 
      5 #include<Winsock2.h>
      6 #include <windows.h>
      7 #include<stdio.h>
      8 #include<stdlib.h>
      9 #pragma comment(lib,"ws2_32.lib")
     10 #define PORT 5000
     11 class MySocket
     12 {
     13 private:
     14     SOCKET accept;
     15     struct sockaddr_in clientAddr;
     16 public:
     17     MySocket(SOCKET a, struct sockaddr_in c)
     18     {
     19         accept = a;
     20         clientAddr = c;
     21     }
     22     void setAccept(SOCKET a)
     23     {
     24         accept = a;
     25     }
     26     void setClientAddr(struct sockaddr_in c)
     27     {
     28         clientAddr = c;
     29     }
     30     SOCKET getAccept()
     31     {
     32         return accept;
     33     }
     34     struct sockaddr_in getClientAddr()
     35     {
     36         return clientAddr;
     37     }
     38 };
     39 DWORD WINAPI ThreadFuc(LPVOID lparam)
     40 {
     41     MySocket* mSocket = (MySocket*)lparam;                    //接收主线程传来的参数
     42     char buf[] = "Hello, How are you!";                    //需要发送的信息
     43     int iSend = 0;
     44     //输出客户端IP、端口
     45     printf("accept() client IP:[%s], port:[%d]
    ", inet_ntoa(mSocket->getClientAddr().sin_addr), ntohs(mSocket->getClientAddr().sin_port));
     46     //给连接的客户发送消息
     47     iSend = send(mSocket->getAccept(), buf, sizeof(buf), 0);
     48     if (iSend == SOCKET_ERROR)
     49     {
     50         printf("send() failed:%d
    ", WSAGetLastError());
     51     }
     52     else if (iSend == 0)
     53         printf("send() failed,no message send successfully
    ");
     54     else
     55         printf("send() byte:%d
    ", send);
     56     closesocket(mSocket->getAccept());                            //关闭套接字
     57     return 0;
     58 }
     59 
     60 void main()
     61 {
     62     int port = PORT;                                    //端口
     63     WSADATA wsaData;                                    //存储系统传回的关于Winsock的资料
     64     SOCKET sListen, sAccept;                            //套接字
     65     int iLen;                                            //客户地址长度
     66     struct sockaddr_in serv, cliet;                        //服务器、客户的地址
     67 
     68     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)        //函数WSAStartup用以打开Winsock
     69     {
     70         printf("Winsock load failed
    ");
     71         return;
     72     }
     73 
     74     sListen = socket(AF_INET, SOCK_STREAM, 0);            //创建套接字,TCP协议
     75     if (sListen == INVALID_SOCKET)                        //socket调用成功返回套接字对象,失败返回INVALID_SOCKET
     76     {
     77         printf("socket failed:%d
    ", WSAGetLastError());
     78         return;
     79     }
     80 
     81     serv.sin_family = AF_INET;                            //网络中标识不同设备使用的地址类型,对于IP地址,类型是AF_INET
     82     serv.sin_port = htons(port);                        //socket对应的端口号
     83     serv.sin_addr.s_addr = htonl(INADDR_ANY);            //封装了IP地址
     84     if (bind(sListen, (LPSOCKADDR)&serv, sizeof(serv)) == SOCKET_ERROR)        //绑定套接字
     85     {
     86         printf("bind() failed:%d
    ", WSAGetLastError());
     87         return;
     88     }
     89 
     90     if (listen(sListen, 5) == SOCKET_ERROR)                //监听
     91     {
     92         printf("listen() failed:%d
    ", WSAGetLastError());
     93         return;
     94     }
     95 
     96     iLen = sizeof(cliet);                                //初始化客户地址长度
     97 
     98     while (1)                                            //进入循环,等待客户连接请求
     99     {
    100         sAccept = accept(sListen, (struct sockaddr*)&cliet, &iLen);    //客户端的套接字
    101         if (sAccept == INVALID_SOCKET)                    //接受连接请求失败
    102         {
    103             printf("accept() failed:%d
    ", WSAGetLastError());
    104             break;
    105         }
    106         else
    107         {
    108             MySocket* mSocket = new MySocket(sAccept, cliet);
    109             HANDLE thread = CreateThread(NULL, NULL, ThreadFuc, mSocket, NULL, NULL);
    110         //    closesocket(sAccept);不能关闭,关闭则不行。
    111         }
    112     }
    113     closesocket(sListen);                            //关闭套接字
    114     WSACleanup();                                    //关闭Winsock
    115     while (1);
    116 }
    server
     1 /*
     2 客户端程序
     3 */
     4 #include<WinSock2.h>
     5 #include<stdio.h>
     6 #pragma comment(lib,"ws2_32.lib")
     7 #define PORT 5000
     8 #define BUFFER 1024
     9 
    10 void main(int argc, char *argv[])
    11 {
    12     WSADATA wsaData;
    13     SOCKET client;
    14     int port = PORT;
    15     int iLen;                                                //从服务器接收的数据长度
    16     char buf[BUFFER];                                        //接收数据的缓冲
    17     struct sockaddr_in serv;                                //服务器端地址
    18     memset(buf, 0, sizeof(buf));                            //接受数据缓冲区初始化
    19 
    20     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)            //函数WSAStartup用以打开Winsock
    21     {
    22         printf("Winsock load failed
    ");
    23         return;
    24     }
    25 
    26     serv.sin_family = AF_INET;                                //需要连接服务器地址信息,AF_INET表示IP协议
    27     serv.sin_port = htons(port);                            //端口
    28     //    serv.sin_addr.s_addr = inet_addr(argv[1]);                //IP地址,转为二进制表示的字节IP地址,argv表示cmd下输入的参数
    29     serv.sin_addr.s_addr = inet_addr("192.168.0.21");
    30     client = socket(AF_INET, SOCK_STREAM, 0);                //客户端套接字,流套接字表示使用TCP协议
    31     if (client == INVALID_SOCKET)                            //创建套接字失败
    32     {
    33         printf("socket() failed:%d
    ", WSAGetLastError());
    34         return;
    35     }
    36 
    37     //连接服务器
    38     if (connect(client, (struct sockaddr*)&serv, sizeof(serv)) == INVALID_SOCKET)
    39     {
    40         printf("connet() failed:%d
    ", WSAGetLastError);
    41         return;
    42     }
    43     else
    44     {
    45         iLen = recv(client, buf, sizeof(buf), 0);            //从服务器接收数据
    46         if (iLen = 0)
    47             return;
    48         else if (iLen == SOCKET_ERROR)
    49         {
    50             printf("recv() failed:%d
    ", WSAGetLastError());
    51             return;
    52         }
    53         printf("recv() data from server:%s
    ", buf);
    54     }
    55 
    56     closesocket(client);                                    //关闭套接字
    57     WSACleanup;                                                //关闭Winsock
    58 
    59     //    system("pause");    //程序暂停
    60     printf("press any key to continue");                    //让程序等待
    61     while (1);
    62 }
    client

     

  • 相关阅读:
    有关phpmailer的详细介绍及使用方法
    威盾解密
    PHP正则表达式验证是否含有中文
    php防止重复提交表单
    simplexml 对xml的增删改操作
    Javascript正则表达式完全学习手册
    利用JS做到隐藏div和显示div
    js控制div显示与隐藏
    后台登陆地址
    MVC 自定义路由
  • 原文地址:https://www.cnblogs.com/starf/p/3623421.html
Copyright © 2011-2022 走看看