一、安装实验环境
这次实验使用的是C/C++来编写套接字程序,可以安装DEVC++、VC6.0、CodeBlocks等,在这里我们选择CodeBlocks。下载地址:,我们进入网址选择带MinGW环境(C语言调试环境)的程安装文件,这样我们才能运行我们的c/c++程序。 codeblocks安装完成之后,要引入libws2_32.a库,由于MinGW本身貌似没有自带libws2_32.a,可以在下面这个链接中下载链接: 提取码:v80g 。
下载完成后,要把这个文件解压出来放在codeblocks安装目录,MinGW的lib文件夹下面,如图 之后,打开CodeBlocks软件,选中菜单栏里面的setting下的compile,然后选中compile—>Link settings—>Add,在安装位置中找到刚刚放进去的libws2_32,然后添加,效果如下,点击OK,库的导入就完成了,此时编程的时候就可以include<winsock.h>库。
二、编写程序并调试程序
分别创建client和server两个工程,将代码复制到对应的程序中去。
然后编译并运行,这个时候,代码如果没有问题的话将会在程序的目录下生成exe文件。这时要注意,在软件里面不能同时运行两个exe文件,这个时候我们就要找到你对应的c/c++程序的目录下面的exe文件然后打开并运行他们。如果你不知道你的创建程序的位置在哪儿了不要紧,在你的程序这里鼠标右键选择properties,在general里面就可以看到你程序的在计算机中的位置了 然后我们到这个位置下去,然后找到bin目录–>debug,就可以看到exe文件了,然后就可以运行它,图中演示的是找到client的exe文件,server.exe也是同理。
然后,我们运行他们,出现两个窗口,一个是客户端的,一个是服务器的,然后奇妙的事情就发生了,可以在两边进行神奇的对话了。
三、实验代码
下面是代码(带有详细注释)
//服务器代码 #include <stdio.h> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") int main(int argc, char* argv[]) { WSADATA wsaData; WORD sockVersion = MAKEWORD(2,2); //指定加载2.2版本 if(WSAStartup(sockVersion,&wsaData)!= 0) //该函数执行成功后返回0。则如果不成功的话return 0,程序终止 { return 0; } SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //创建套接字,AF_INET表示IPV4地址族,SOCK_DGRAM表示数据包套接字,IPPROTO_UDP说明支持的是UDP协议 if(serSocket == INVALID_SOCKET) { //创建的套接字非法 printf("socket error !"); return 0; } sockaddr_in serAddr; serAddr.sin_family = AF_INET; //设置地址族为IPV4 serAddr.sin_port = htons(8888); //设置端口号为8888 serAddr.sin_addr.S_un.S_addr = INADDR_ANY; //设置IP地址为INADDR_ANY if(bind(serSocket, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR) //将一个Socket绑定到特定的IP地址和端口上 { printf("bind error !"); closesocket(serSocket); return 0; //绑定失败,输出"bind error"程序结束 } sockaddr_in remoteAddr; int nAddrLen = sizeof(remoteAddr); char recvData[255]; //用来接收数据的字符数组 char sentData[255]; //用来发送数据的字符数组 while (true) { int ret = recvfrom(serSocket, recvData, 255, 0, (sockaddr *)&remoteAddr, &nAddrLen); //从特定的socket地址接受数据,成功则返回实际传送出去的字符数,失败返回-1 if (ret > 0) { recvData[ret] = 0x00; printf("接受到一个连接:%s ", inet_ntoa(remoteAddr.sin_addr)); if(strcmp(recvData,"666")==0) { //退出 printf(" 开始退出 "); closesocket(serSocket); //关闭通信 WSACleanup(); return 0; } printf(recvData); } printf(" 请输入要发送的数据. "); gets(sentData); //读入一行字符串 sendto(serSocket, sentData, strlen(sentData), 0, (sockaddr *)&remoteAddr, nAddrLen); //从特定的socket地址接受发送,成功则返回接收到的字符数,失败则返回-1 } }
//客户端代码 #include <stdio.h> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") int main(int argc, char* argv[]) { WORD socketVersion = MAKEWORD(2,2); //指定加载2.2版本 WSADATA wsaData; if(WSAStartup(socketVersion,&wsaData)!= 0) { return 0; } SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//创建套接字 sockaddr_in sin; sin.sin_family = AF_INET; //设置地址族为IPV4 sin.sin_port = htons(8888); //设置端口号为8888 sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //设置IP地址为127.0.0.1 int len = sizeof(sin); //说明地址信息的长度 char sentData[255]; //发送数据的存放位置,字符数组 char recvData[255]; //接收数据的存放位置,字符数组 while (1) { printf(" 请输入传给服务器的数据,以666结束. "); gets(sentData); //若两个字符串相等为0,否则为非0 if(strcmp(sentData,"666")!=0) { printf("开始发送数据 "); //不是结束标识 sendto(sclient, sentData, strlen(sentData), 0, (sockaddr *)&sin, len); //发送完数据,规定开始接受数据 int ret = recvfrom(sclient, recvData, 255, 0, (sockaddr *)&sin, &len); if(ret > 0) { //打印接收的数据 recvData[ret] = 0x00; printf(recvData); } }else { //退出 strcpy(sentData,"666"); sendto(sclient, sentData, strlen(sentData), 0, (sockaddr *)&sin, len); closesocket(sclient); WSACleanup(); return 0; } } }
最后实验还要求服务器将客户端发送的数据经大小写转换后,重新发回客户端,在这里提供一下将一个字符串进行大小写转换的一种方式。
#include <iostream> #include <string.h> using namespace std; int main() { char recvData[255]; cout<<"Please input a string:"; gets(recvData); for( int i = 0 ; i < strlen(recvData) ; i++) { if(recvData[i] >= a && recvData[i] <= z){ recvData[i] = recvData[i] - 32; } else if(recvData[i] >= A && recvData[i] <= Z) { recvData[i] = recvData[i] + 32; } } cout << recvData << endl; return 0; }
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/290890.html