1. 两天计算机通信需要协议,通信的两台计算机IP必须唯一 2. 同一个计算机可以进行多个应用程序与其他计算机通信,IP地址唯一,而端口号是区别同一计算机(同一IP)的唯一标示。 3. 实际上就类似于一个办公室的总机号码(IP)和分机号码(端口号) 4. 协议:为了进行网络中的数据交换(通信)而建立的规则、标准或约定 5. 协议=语义+语法+规则 6. 不同层具有各自不同的协议 7. 上层使用下层提供的服务,实际通信在最底层完成 8. 对等层实体之间虚拟通信| 9. TCP:面向连接的可靠的传输协议 10. UDP:面向无连接的不可靠的传输协议 11. 端口是一种抽象的软件结构。应用程序通过系统调用与某端口建立连接后,传输层传给端口的数据都被响应的进行所接收,相应进程发给传输层的数据都通过该端口输出。 12. 端口用一个整数型标示符来表示。端口号跟协议相关,TCP/IP传输层的两个协议TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立。 13. 端口使用一个16位的数字来表示,它的范围是0~65535,1024以下的端口号保留给预定义的服务。例如:http使用的是80端口。 14. socket(套接字):windows sockets只支持一个通信区域:网际域(AF_INET),这个域被使用网际协议簇通信的进程使用。 15. C/S模式:客户机向服务器提出请求,服务器接收到请求后,提供相应的服务。 16. 套接字的类型 a) 流式套接字:(SOCK_STREAM):面向连接可靠的数据传输服务,按顺序接收 b) 数据包式套接字:(SOCK_DGRAM):无连接服务。接收顺序混乱。 c) 原始套接字(SOCK_RAM) 17. 基于TCP(面向连接)的socket编程 a) 服务器端程序: i. 创建套接字socket ii. 将套接字绑定到一个本地地址和端口上bind iii. 将套接字设为监听模式,准备接收客户请求listen iv. 等待客户请求到了;当请求到来后,接收连接请求,返回一个新的对应于此次连接的套接字accept v. 用返回的套接字和客户端进行通信rend/recv vi. 返回,等待另一客户请求 vii. 关闭套接字 b) 客户端程序: i. 创建套接字socket ii. 向服务端发出连接请求connect iii. 和服务器端进行通信rend/recv iv. 关闭套接字 18. 基于UDP的socket编程 a) 服务器端(接收端)程序: i. 创建套接字socket ii. 将套接字绑定到一个本地地址和端口上bind iii. 等待接收数据recv/from iv. 关闭套接字 b) 客户端(发送端)程序: i. 创建套接字socket ii. 向服务器发送数据sendto iii. 关闭套接字
struct sockaddr { u_short sa_family; char sa_data[14]; }; c) 监听
d) 接受连接
g) 需要的文件 #include <winsock2.h> 需要连接一个动态链接库:ws2_32.lib 22. 服务器端: a) Socket b) 连接:connect
c) 接收:recv d) 发送:send e) 关闭:closesocket Tcp服务端程序:
======================================================= #include <WINSOCK2.H> #include <stdio.h> main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); listen(sockSrv,5); SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); while(1) { SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len); char sendBuf[100]; sprintf(sendBuf,"Welcome %s to 刘洼村",inet_ntoa(addrClient.sin_addr)); send(sockConn,sendBuf,strlen(sendBuf)+1,0); char recvBuf[100]; recv(sockConn,recvBuf,100,0); printf("%s\n",recvBuf); closesocket(sockConn); } }
24. Tcp客户端程序:
[cpp] view plaincopy #include <WINSOCK2.H> #include <stdio.h> void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//服务器端的地址 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); char recvBuf[100]; recv(sockClient,recvBuf,100,0); printf("%s\n",recvBuf); send(sockClient,"This is 刘洼村",strlen("This is 刘洼村")+1,0); closesocket(sockClient); WSACleanup(); }
25. 运行之后,开启了6个客户端,一个服务器端。程序运行效果: 26. 面向UDP的连接 27. 服务器:socket a) bind b) 接收数据:
c) 关闭closesocket d) Cleanup 28. UDP服务器端程序:
[cpp] view plaincopy #include <WINSOCK2.H> #include <stdio.h> void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); char recvBuf[100]; recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len); printf("%s\n",recvBuf); closesocket(sockSrv); WSACleanup(); }
28. UDP客户端: a) socket定义 b) 发送:
29. UDP客户端程序
[cpp] view plaincopy #include <WINSOCK2.H> #include <stdio.h> void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); sendto(sockClient,"Hello 刘洼村",strlen("Hello 刘洼村")+1,0, (SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); closesocket(sockClient); WSACleanup(); }
30. 注意:每个程序都要加上ws2_32.lib链接库。如下添加: By 刘洼村 |
|