计算机网络实验:UDP套接字编程

一、安装实验环境

这次实验使用的是C/C++来编写套接字程序,可以安装DEVC++、VC6.0、CodeBlocks等,在这里我们选择CodeBlocks。下载地址:http://www.codeblocks.org/downloads/26,我们进入网址选择带MinGW环境(C语言调试环境)的程安装文件,这样我们才能运行我们的c/c++程序。
在这里插入图片描述
codeblocks安装完成之后,要引入libws2_32.a库,由于MinGW本身貌似没有自带libws2_32.a,可以在下面这个链接中下载链接:https://pan.baidu.com/s/1vFJUWk2czUu24YWMJJnZWA 提取码: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 \r\n", inet_ntoa(remoteAddr.sin_addr));
			if(strcmp(recvData,"666")==0)
			{
    
    
				//退出
				printf("\n开始退出\n");
				closesocket(serSocket);	//关闭通信
				WSACleanup();
				return 0;
			}
			printf(recvData);
		}
		printf("\n请输入要发送的数据.\n");
		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("\n请输入传给服务器的数据,以666结束.\n");
		gets(sentData);
		//若两个字符串相等为0,否则为非0
		if(strcmp(sentData,"666")!=0)
		{
    
    
			printf("开始发送数据\n");
			//不是结束标识
			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;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43715171/article/details/106058795
今日推荐