zoukankan      html  css  js  c++  java
  • Windows Socket的UDP和TCP编程介绍

    1:网络中进程之间如何通信

      为了实现进程之间通信,首要解决的问题是如何唯一标识一个进程,在本地可以通过进程PID来唯一标识一个进程,但是在网络中则是行不通的,其实TCP/IP协议族已经帮我们解决了这个问题,网络层的"ip 地址"可以唯一标识网络中的主机,而"传输层的 协议+端口"可以唯一标识主机中的应用程序(进程)。这样利用(ip地址,谢谢,端口)就可以标识网络中的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。而现在几乎所有网络应用程序都是采用socket来通信的,那么什么是socket呢?

    2:套接字(socket)

      socket起源于Unix,而Unix/Linux基本哲学之一就是"一切皆文件",都可以用"打开Open -> 读写write/read ->关闭close"模式来操作,socket就是该模式的一个实现,socket就是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),说白了Socket就是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。socket把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说就是一组简单的接口。让socket去组织数据,以符合指定的协议。

      随着Unix的应用推广,套接字有被引进了windows等操作系统,套接字通常只与同一区域的套接字交换数据,windows只支持一个通信区域,网际域(AF_INET),这个域被使用网际协议簇的通信进程。

    3:客户机/服务器模式

      在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户机/服务器模式(client/server),即客户向服务器提出请求,服务器接受到请求后提出相应的服务。

    服务器:

     (1):首先服务器先要启动,打开一个通信通道并告知本机,它愿意在某一个地址和端口上接收客户请求。

     (2):等待客户请求到达该端口。

     (3):接收服务请求,处理该客户请求,服务完成后,关闭此进程与客户的通信链路,并终止。

     (4):返回第二步,等待另一个客户请求

     (5):关闭服务器

    客户方:

     (1):打开一个通信通道,并连接到服务器所在的主机特定的端口。

     (2):向服务器发送请求,等待并接收应答,继续提出请求。

     (3):请求结束后关闭通信信道并终止

    4:基于TCP(面向连接)的socket编程

      

    服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listlen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了,客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

    5:基于UDP(面向无连接)的socket编程

      

    服务器先创建socket,将socket绑定(bind)一个本地地址和端口上,等待数据传输(recvfrom).这个时候如果有个客户端创建socket,并且向服务器发送数据(sendto),服务器就建立了连接,实现了数据的通信,连接结束后关闭连接.

    6:UDP例子

       Server端

     1 //注:需要在stdafx.h 里面添加 #pragma comment(lib, "ws2_32.lib")
     2 #include"stdafx.h"
     3 #include <winsock2.h>
     4 #include <ws2tcpip.h>
     5 #include <stdio.h>
     6 #include <windows.h>
     7 using namespace std;  
     8 
     9 #pragma comment(lib, "ws2_32.lib")          //add ws2_32.lib  
    10 
    11 int main()
    12 {
    13     WORD wVersionRequested;
    14     WSADATA wsaData;
    15     int err;
    16 
    17     wVersionRequested = MAKEWORD(2, 2);
    18 
    19     err = WSAStartup(wVersionRequested, &wsaData);
    20     if (err != 0) 
    21     {                                 
    22         printf("WSAStartup failed with error: %d
    ", err);
    23         return 1;
    24     }
    25 
    26     if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
    27     {
    28         printf("Could not find a usable version of Winsock.dll
    ");
    29         WSACleanup();
    30         return 1;
    31     }
    32     else
    33     {
    34         printf("The Winsock 2.2 dll was found okay
    ");
    35     }
    36 
    37     SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM, 0); //创建一个socket句柄;
    38     if( sockSrv == INVALID_SOCKET )
    39     {  
    40         printf("socket() fail:%d
    ",WSAGetLastError());
    41         return -2;  
    42     } 
    43 
    44     SOCKADDR_IN  addrServ;
    45     memset(&addrServ,0,sizeof(addrServ));
    46     addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    47     addrServ.sin_family = AF_INET;
    48     addrServ.sin_port = htons(4999); //从"主机字节顺序" 转变为 "网络字节顺序"
    49 
    50     err = bind(sockSrv,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); //把socket 绑定到指定地址上
    51     if( err != 0 )  
    52     {  
    53         printf("bind()fail:%d
    ",WSAGetLastError());  
    54         return -3;  
    55     } 
    56 
    57     SOCKADDR_IN  addrClient;
    58     memset(&addrClient,0,sizeof(addrClient)); //在设置每个地址成员之前,整个addr结构应该被初始化0;
    59     int length = sizeof(SOCKADDR);
    60     char recvBuf[100];
    61     printf("waiting for client connect!!!!
    ");
    62     recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&length);
    63 
    64     printf("recvfrom client:: %s
    ",recvBuf);
    65 
    66     closesocket(sockSrv);
    67 
    68     WSACleanup();
    69 
    70     system("PAUSE");
    71     return 0;
    72 }

    Client端

     1 // 注:需要在stdafx.h 里面添加 #pragma comment(lib, "ws2_32.lib")
     2 //
     3 #include"stdafx.h"
     4 #include <winsock2.h>
     5 #include <ws2tcpip.h>
     6 #include <stdio.h>
     7 #include <windows.h>
     8 using namespace std;  
     9 
    10 #pragma comment(lib, "ws2_32.lib")          //add ws2_32.lib  
    11 
    12 int main()
    13 {
    14     WORD wVersionRequested;
    15     WSADATA wsaData;
    16     int err;
    17 
    18     wVersionRequested = MAKEWORD(2, 2);
    19 
    20     err = WSAStartup(wVersionRequested, &wsaData);
    21     if (err != 0) 
    22     {                                 
    23         printf("WSAStartup failed with error: %d
    ", err);
    24         return 1;
    25     }
    26 
    27     if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
    28     {
    29         printf("Could not find a usable version of Winsock.dll
    ");
    30         WSACleanup();
    31         return 1;
    32     }
    33     else
    34     {
    35         printf("The Winsock 2.2 dll was found okay
    ");
    36     }
    37 
    38 
    39     SOCKET sockClient = socket(AF_INET,SOCK_DGRAM, 0);
    40 
    41     SOCKADDR_IN  addrServ;
    42     memset(&addrServ,0,sizeof(addrServ));
    43     addrServ.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    44     addrServ.sin_family = AF_INET;
    45     addrServ.sin_port = htons(4999);
    46     printf("begin to send data to server::Hello
    ");
    47     sendto(sockClient,"Hello
    ",strlen("Hello
    ")+1,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
    48 
    49     closesocket(sockClient);
    50 
    51     system("PAUSE");
    52     WSACleanup();
    53 
    54     return 0;
    55 }

    输出的结果为:

     7:TCP例子

     Server端

     1 #include"stdafx.h"
     2 #include <winsock2.h>  
     3 #include <iostream>  
     4 
     5 #include <string.h>  
     6 using namespace std;  
     7 
     8 #pragma comment(lib, "ws2_32.lib")          //add ws2_32.lib  
     9 
    10 
    11 const int DEFAULT_PORT = 8000;  
    12 int main(int argc,char* argv[])  
    13 {  
    14 
    15     WORD    wVersionRequested;  
    16     WSADATA wsaData;  
    17     int     err,iLen;  
    18     wVersionRequested   =   MAKEWORD(2,2);  
    19 
    20     err =  WSAStartup(wVersionRequested,&wsaData); 
    21     if( err!=0 )  
    22     {  
    23         printf("WSAStartup failed with error: %d
    ", err); 
    24         return -1;  
    25     }  
    26     if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) 
    27     {
    28         printf("Could not find a usable version of Winsock.dll
    ");
    29         WSACleanup();
    30         return 1;
    31     }
    32     else
    33     {
    34         printf("The Winsock 2.2 dll was found okay
    ");
    35     }
    36 
    37     SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);  
    38     if( sockSrv == INVALID_SOCKET )
    39     {  
    40         printf("socket() fail:%d
    ",WSAGetLastError());
    41         return -2;  
    42     }  
    43 
    44     SOCKADDR_IN addrSrv;  
    45     memset(&addrSrv,0,sizeof(addrSrv));
    46     addrSrv.sin_family = AF_INET;  
    47     addrSrv.sin_addr.s_addr = htonl(INADDR_ANY);  
    48     addrSrv.sin_port = htons(DEFAULT_PORT);  
    49 
    50     err = bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));  
    51     if( err != 0 )  
    52     {  
    53         printf("bind()fail:%d
    ",WSAGetLastError());  
    54         return -3;  
    55     }  
    56 
    57     err = listen( sockSrv,5 );//listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数
    58     if( err != 0 )  
    59     {  
    60         printf("listen()fail:%d
    ",WSAGetLastError());
    61         return -4;  
    62     } 
    63     printf("Server waitting...!!!!!
    ");  
    64     SOCKADDR_IN addrClt;  
    65     int len = sizeof(SOCKADDR);  
    66     memset(&addrClt,0,len);
    67 
    68     while(1)  
    69     {  
    70         SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrClt,&len);  
    71         char sendBuf[1024],hostname[100];  
    72         if( gethostname(hostname,100) != 0 ) 
    73         {
    74             strcpy_s(hostname,strlen("None")+1,"None");  
    75         }
    76         sprintf_s(sendBuf,sizeof(sendBuf),"Welecome %s connected to %s!",inet_ntoa(addrClt.sin_addr),hostname);  
    77 
    78         err = send(sockConn,sendBuf,strlen(sendBuf)+1,0);  
    79 
    80         char recvBuf[1024]="";  
    81         iLen = recv(sockConn,recvBuf,1024,0);  
    82 
    83         recvBuf[iLen]=''; 
    84         printf(recvBuf);
    85 
    86         closesocket(sockConn);  
    87     }  
    88 
    89     closesocket(sockSrv);  
    90 
    91     WSACleanup();  
    92     return 0;  
    93 }  

    Client端

     1 // client.cpp : 定义控制台应用程序的入口点。
     2 //
     3 #include"stdafx.h"
     4 #include <winsock2.h>  
     5 #include <iostream>  
     6 
     7 #include <string.h>  
     8 using namespace std;  
     9 
    10 #pragma comment(lib, "ws2_32.lib")          
    11 
    12 
    13 const int DEFAULT_PORT = 8000;  
    14 int main(int argc,char* argv[])  
    15 {  
    16 
    17     WORD    wVersionRequested;  
    18     WSADATA wsaData;  
    19     int     err,iLen;  
    20     wVersionRequested   =   MAKEWORD(2,2);
    21 
    22     err =   WSAStartup(wVersionRequested,&wsaData); //load win socket  
    23     if( err != 0 )  
    24     {  
    25         printf("WSAStartup failed with error: %d
    ", err);
    26         return -1;  
    27     }  
    28 
    29     SOCKET sockClt = socket(AF_INET,SOCK_STREAM,0);  
    30     if( sockClt == INVALID_SOCKET )
    31     {  
    32         printf("socket() fail:%d
    ",WSAGetLastError());
    33         return -2;  
    34     }  
    35 
    36     SOCKADDR_IN addrSrv;  
    37     memset(&addrSrv,0,sizeof(addrSrv));
    38     addrSrv.sin_family = AF_INET;  
    39     addrSrv.sin_addr.s_addr = inet_addr("127.0.0.1");  
    40     addrSrv.sin_port = htons(DEFAULT_PORT);  
    41 
    42     err = connect(sockClt,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));  
    43 
    44     if(err ==INVALID_SOCKET)  
    45     {  
    46         printf("connect()fail:%d
    ",WSAGetLastError());   
    47         return -1;  
    48     }  
    49 
    50     char sendBuf[1024],hostname[100];  
    51     if( gethostname(hostname,100) != 0 ) //如果没有错误的时候gethostname会返回0;
    52     {
    53         strcpy_s(hostname,strlen("None")+1,"None");  
    54     }
    55     strcpy_s(sendBuf,strlen(hostname)+1,hostname);  
    56     strcat_s(sendBuf,sizeof(sendBuf)," have connected to you!");  
    57     err = send(sockClt,sendBuf,strlen(sendBuf)+1,0);  
    58 
    59     char recvBuf[1024]="";  
    60     iLen = recv(sockClt,recvBuf,1024,0);  
    61 
    62     if( iLen == 0 )  
    63     {
    64         return -3; 
    65     }
    66     else if( iLen == SOCKET_ERROR )
    67     {  
    68         printf("recv() fail:%d
    ",WSAGetLastError()); 
    69         return -4;  
    70     }  
    71     else  
    72     {  
    73         recvBuf[iLen] = '';  
    74         printf(recvBuf);  
    75         printf("
    ");
    76     }  
    77     closesocket(sockClt);  
    78 
    79     WSACleanup();  
    80     system("PAUSE");  
    81     return 0;  
    82 }  

    输出的结果为

  • 相关阅读:
    Python3---filter,map,reduce
    老男孩-day2作业-计算器
    Python 简易购物系统--老男孩作业
    老男孩-day1作业二
    老男孩-day1作业一
    Axure8.0图片旋转注意
    CentOS6.5部署KVM及实现在线迁移
    CentOS 6.5 安装部署iSCSi共享存储
    CentOS 6.5 安装部署KVM
    CentOS6.5部署L2TP over IPSec
  • 原文地址:https://www.cnblogs.com/cxq0017/p/6497352.html
Copyright © 2011-2022 走看看