面向非连接的基础Socket编程

该实验介绍了如何使用WinSock函数实现基于UDP的数据报套接字编程。实验目标是理解无连接Socket通信流程,通过发送端和接收端程序实现信息的双向传输。在服务器端,创建数据报式套接字,绑定IP和端口,接收并回送信息;在客户端,同样创建数据报式套接字,发送并接收信息。当接收到特定退出指令时,双方程序终止。实验展示了UDP的无连接特性,不保证数据的顺序和可靠性。
摘要由CSDN通过智能技术生成

实验三 面向非连接的基础Socket编程

一、 实验目的

1.了解面向非连接的Socket通信流程。
2.掌握使用WinSock函数编写面向非连接的网络应用程序的方法。

二、实验内容

利用数据报套接字编程实现网络通信程序。要求如下:
1.发送端从控制台读取信息并发送,接收端接收信息后打印信息然后回送收到的信息。信息的发送和接收可以多次进行。当收到的信息为“exit”时,双方程序退出。
2.启动发送端和接收端程序进行信息收发测试。

三、实验原理

面向非连接就是udp通信
在这里插入图片描述

数据报式套接字提供无连接的书籍传输服务。数据包被独立的发送,数据可能丢失或重复。
在无连接服务中,每次数据传输并不需要建立连接,因此每个分组数据包中必须包含完整的目的地址,并且每个数据包都独立的在网络中传输。无连接服务不能保证分组的先后顺序,不能保证数据传输的可靠性。Udp提供无连接的数据报服务。
面向非连接的socket通信流程比较简单,在服务器程序中不需要调用listen()和accept()函数来等待客户端的连接;在客户端程序中也不需要与服务器建立连接,而是直接向服务器发送数据。

四、实验步骤

Server:
1.建立数据报式套接字,返回套接字号s【socket( )】
2.套接字s与本地地址(IP+端口)绑定【bind( )】
3.在套接字ns上读/写数据,直到结束【sendto( )】【recvfrom( )】
4.关闭套接字ns 【closesocket( )】

Client:
1.建立数据报式套接字,返回套接字号s【socket( )】
2.在套接字ns上读/写数据,直到结束【sendto( )】【recvfrom( )】
3.关闭套接字ns 【closesocket( )】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、实验小结

附:程序源代码

Server:

// Udp_server.cpp: 定义控制台应用程序的入口点。
//
//相关头文件
#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>
#include <iostream>
#pragma comment(lib,"WS2_32.lib")
 
int main()
{
	//初始化
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		printf("WSAStartup initialization failed");
		return 0;
	}
 
	//变量的声明,赋值
	SOCKET RecvSocket;
	sockaddr_in RecvAddr;
	int Port = 8888;
	char RecvBuf[1024]; //接收缓冲
	char SendBuf[1024]; //发送缓冲
	int BufLen = 1024;
	sockaddr_in SenderAddr;
	int SenderAddrSize = sizeof(SenderAddr);
 
	//创建接受数据的socket
	RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
	//绑定ip和端口
	RecvAddr.sin_family = AF_INET;
	RecvAddr.sin_port = htons(Port);
	RecvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	bind(RecvSocket, (SOCKADDR *)&RecvAddr, sizeof(RecvAddr));
 
	
	printf("UDP Server start successed,waiting for recieve data...\n");
	while (true) {
 
		//接收
		int re_number = recvfrom(RecvSocket,
			RecvBuf,
			BufLen,
			0,
			(SOCKADDR *)&SenderAddr,
			&SenderAddrSize
		);
		if (re_number > 0) {
			printf("Recieved UDP data from client :%s\n", &RecvBuf);
			if (strcmp(RecvBuf, "exit") == 0)
			{
				closesocket(RecvSocket);
				return 0;
			}
		}
 
		//发送
		gets_s(SendBuf); //获取键盘输入
		
		//发送函数
		int send_number = sendto(RecvSocket, 
			SendBuf, BufLen, 
			0, 
			(SOCKADDR *)&SenderAddr, 
			sizeof(SenderAddr)
		);
		printf("server_to_client: %s\n", SendBuf);
		if (strcmp(SendBuf, "exit") == 0){
			closesocket(RecvSocket);
			return 0;
		}
	}
		if (WSACleanup() == SOCKET_ERROR)
			printf("WSACleanup failed");
		return 0;
	
}

Client:

// Udp_Client.cpp: 定义控制台应用程序的入口点。
//
//相关头文件
#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>
#include <iostream>
#include <Ws2tcpip.h>  //第35行函数需要此头文件
using namespace std;
#pragma comment(lib,"WS2_32.lib")
 
int main()
{
	//初始化
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		printf("WSAStartup initialization failed");
		return 0;
	}
 
	//变量的声明,赋值
	SOCKET SendSocket; 
	sockaddr_in RecvAddr; //服务器端的地址
	int Port = 8888;
	char SendBuf[1024];
	char RecvBuf[1024];
	int BufLen = 1024;
	
	//创建soclket
	SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	
	//设置服务器地址
	RecvAddr.sin_family = AF_INET;
	RecvAddr.sin_port = htons(Port);
	//RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //vs2017不支持此写法
	InetPton(AF_INET, _T("127.0.0.1"), &RecvAddr.sin_addr.s_addr);
	int RecvAddrSize = sizeof(RecvAddr);
	//向服务器发送数据
	printf("UDP Client start successed,waiting for sent data...\n");
	
	while (true) {
		//scanf_s("%s",SendBuf);    //如果使用这个函数,则会向客户端发送死循环的“烫”,原因是没有结束符,空字符串打印出来就是乱码!
		
		//发送
		gets_s(SendBuf);
		int  st = sendto(SendSocket,
			SendBuf,
			BufLen,
			0,
			(SOCKADDR *)&RecvAddr,
			sizeof(RecvAddr)
			);
		if (strcmp(SendBuf, "exit") == 0) {
			closesocket(SendSocket);
			return 0;
		}
		
		//接受
		int recv_number = recvfrom(SendSocket, RecvBuf, BufLen, 0, (SOCKADDR *)&RecvAddr, &RecvAddrSize);
		printf("From server: %s\n" ,RecvBuf);
		if (strcmp(RecvBuf, "exit") == 0) {
			closesocket(SendSocket);
			return 0;
		}
		if (st == SOCKET_ERROR) {
			printf("Exiting.\n");
			closesocket(SendSocket);
			WSACleanup();
			return -1;
		}
	}

 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半夏风情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值