您的位置:首页 > 理论基础 > 计算机网络

Windows Socket的UDP和TCP编程介绍

2017-03-03 16:33 127 查看
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\n", 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\n");
29         WSACleanup();
30         return 1;
31     }
32     else
33     {
34         printf("The Winsock 2.2 dll was found okay\n");
35     }
36
37     SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM, 0); //创建一个socket句柄;
38     if( sockSrv == INVALID_SOCKET )
39     {
40         printf("socket() fail:%d\n",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\n",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!!!!\n");
62     recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&length);
63
64     printf("recvfrom client:: %s\n",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\n", 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\n");
30         WSACleanup();
31         return 1;
32     }
33     else
34     {
35         printf("The Winsock 2.2 dll was found okay\n");
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\n");
47     sendto(sockClient,"Hello\n",strlen("Hello\n")+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\n", 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\n");
29         WSACleanup();
30         return 1;
31     }
32     else
33     {
34         printf("The Winsock 2.2 dll was found okay\n");
35     }
36
37     SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);
38     if( sockSrv == INVALID_SOCKET )
39     {
40         printf("socket() fail:%d\n",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\n",WSAGetLastError());
54         return -3;
55     }
56
57     err = listen( sockSrv,5 );//listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数
58     if( err != 0 )
59     {
60         printf("listen()fail:%d\n",WSAGetLastError());
61         return -4;
62     }
63     printf("Server waitting...!!!!!\n");
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]="\0";
81         iLen = recv(sockConn,recvBuf,1024,0);
82
83         recvBuf[iLen]='\0';
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\n", 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\n",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\n",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]="\0";
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\n",WSAGetLastError());
69         return -4;
70     }
71     else
72     {
73         recvBuf[iLen] = '\0';
74         printf(recvBuf);
75         printf("\n");
76     }
77     closesocket(sockClt);
78
79     WSACleanup();
80     system("PAUSE");
81     return 0;
82 }


输出的结果为

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: