第十六课:网络编程
一、UDP发送端:
建一个windows控制台工程,在main函数中加入:
1. 初始化DLL:
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1),&wsaData);
Windows socket编程用到了微软提供的DLL,在使用前要对它进行初始化,Socket编程用到的DLL也分为不同的几个版本,WSAStartup函数的第一个参数就是用户所请求的版本号。
2. 生成socket:
SOCKET s= socket(AF_INET,SOCK_DGRAM,0);
3. Bind:
SOCKADDR_IN sockSrc;
sockSrc.sin_family =AF_INET;
sockSrc.sin_port =htons(3000);
sockSrc.sin_addr .S_un .S_addr =htonl(INADDR_ANY);
bind (s,(SOCKADDR *)&sockSrc,sizeof(SOCKADDR));
说明:
a.bind函数要指定IP地址和端口号:
IP地址:必须是执行这个程序所在计算机的IP地址,将其设定为INADDR_ANY,系统会自动将计算机的正确IP地址填入。
端口号:由于一台计算机可以启动多个网络程序,而IP地址只能保证网络数据到达指定的计算机,所以要指定端口号以区别数据是发给哪个网络程序。端口号是一个两个字节的整数,应把它设在1024到5000之间的值。若设为0,系统会将其设定为一个适当的数值。
B.由于各种计算机的数值读取方式不同(比如PC与UNIX系统就不相同),所以 在指定端口号和IP地址时,要把它们从主机次序转换到网络次序。Htons, htonl函数即实现的这种功能。
4. 发送数据:
SOCKADDR_IN sockDest;
sockDest.sin_family=AF_INET;
sockDest.sin_port =htons(3001);
sockDest.sin_addr.S_un .S_addr =inet_addr("192.168.8.36");
char buf[1024];
strcpy(buf,"hello It315!");
sendto(s,buf,strlen(buf)+1,0,(SOCKADDR*)&sockDest,sizeof(SOCKADDR));
其中:inet_addr用于将固定格式的字符串(形如"192.168.8.36")转换为一个整数。对应的一个函数inet_ntoa用于将整数转换为"192.168.8.36"形式的字符串。
5. 关闭socket:
closesocket(s);
6. 调用
WSACleanup();
7. 包含头文件:
#include "winsock2.h"
8. 加入LIB:
点击菜单ProjectàSettingàLink 在Object/library modules:中加入Ws2_32.lib
二、UDP接收端:
接收端和发送端基本相同,只有第4点不同,将其改为接收数据:
SOCKADDR_IN sockFrom;
char buf[1024];
memset (buf,0,1024);
int len=sizeof(SOCKADDR);
int x=recvfrom(s,buf,1024,0,(SOCKADDR*)&sockFrom,&len);
printf("%s\n",buf);
在main函数前加入#include "stdio.h"。
注意:一定要将接收端bind的端口号设为发送端发送数据的端口号,本例中设为3001。
现在可以测试程序,应该先启动接收端,再启动发送端,因为UDP是一个不可靠的协议,并不保证发送的数据一定到达接收端。
三、TCP服务器端:
1. 初始化DLL:
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1),&wsaData);
2. 生成socket:
SOCKET s= socket(AF_INET, SOCK_STREAM,0);
3. Bind:
SOCKADDR_IN sockSrc;
sockSrc.sin_family =AF_INET;
sockSrc.sin_port =htons(3000);
sockSrc.sin_addr .S_un .S_addr =htonl(INADDR_ANY);
bind (s,(SOCKADDR *)&sockSrc,sizeof(SOCKADDR));
4. 设定socket为监听状态:
listen(s,5);
其中,第二个参数是可以等待连接的最大数目,但它不是一次在给定端口可以建立的连接的最大数目,而是可以放在队列中等待应用程序来接受它们的连接或部分连接的最大数目。
5. 接受连接:
int len=sizeof(SOCKADDR_IN);
SOCKADDR_IN addrClient;
SOCKET sockClient=accept(s,(SOCKADDR*)&addrClient,&len);
Accept函数会产生一个新的socket,在这个新产生的socket上和客房端进行数据交流。
6. 发送和接收数据:
char buf[1024];
strcpy(buf, "hello the world");
send(sockClient,buf,strlen(buf),0);
memset(buf ,0,1024);
recv(sockClient,buf,1024,0);
printf(buf);
7. 关闭socket:
closesocket(sockClient);
closesocket(s);
8. 调用
WSACleanup();
9. 包含头文件:
#include "winsock2.h"
#include "stdio.h"
10. 加入LIB:
点击菜单ProjectàSettingàLink 在Object/library modules:中加入Ws2_32.lib
四、TCP客房端:
前两点与TCP服务器端相同。
3.发出连接请求:
SOCKADDR_IN addrServer;
addrServer.sin_family =AF_INET;
addrServer.sin_port =htons(3000);
addrServer.sin_addr .S_un .S_addr =inet_addr("192.168.8.36");
connect(s,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
4.发送和接收数据:
char buf[1024];
memset(buf,0,1024);
recv(s,buf,1024,0);
printf(buf);
scanf("%s",buf);
send(s,buf,strlen(buf),0);
下同TCP服务器端的7,8,9,10。
测试程序时,应该先启动服务器端,再启动客房端。
评论