TCP/UDP Socket编程(包含C++具体实现代码)

文章介绍了套接字作为应用进程与端到端传输协议(TCP或UDP)间的接口,详细阐述了TCP服务的建立过程,包括服务器的等待连接建立、客户端的主动连接以及服务器如何接受并处理多个客户端的连接请求。同时,提供了TCP和UDP套接字的C++编程示例,展示了服务器如何监听和响应客户端的连接及数据传输。
摘要由CSDN通过智能技术生成

套接字:应用进程与端到端传输协议(TCP或UDP)之间的门户

TCP服务:从一个进程向另一个进程可靠地传输字节流

服务器首先运行,等待连接建立

1:服务器进程必须先处于运行状态

  • 创建欢迎socket
  • 和本地端口捆绑
  • 在欢迎socket上阻塞式等待接收用户的连接

客户端主动和服务器建立连接:

2:创建客户端本地套接字(隐式捆绑到本地port)

  • 指定服务器进程的IP地址和端口号,与服务器进程连接

3 :当与客户端连接请求到来时

  • 服务器接受来自用户端的请求,解除阻塞式等待,返回一个新的socket(与欢迎socket不一样),与客户端通信

            允许服务器与多个客户端通信
    
            使用源IP和源端口来区分不同的客户端
    

4:连接API调用有效时,客户端P与服务器建立了TCP连接

TCP在客户端和服务器进程之间提供了可靠的、字节流(管道)服务

TCP Socket编程:

Server:

#include<iostream>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
//void ErrorSocket{};

int main() {
	cout << "开始" << endl;
	WSADATA wsaData{};
	SOCKET SerSock{}, CliSock{};
	sockaddr_in SerAddr{}, CliAddr{};
	//初始化网络库
	WSAStartup(MAKEWORD(2, 1), &wsaData);
	//创建socket
	SerSock = socket(PF_INET, SOCK_STREAM, 0);
//服务端的信息,IP地址,端口
	SerAddr.sin_family = AF_INET;
	//SerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //绑定地址  
	SerAddr.sin_addr.s_addr = htonl(INADDR_ANY); //宏就是定义0.0.0.0  监听所有IP
	SerAddr.sin_port = htons(6969);  //转成端口
	
	//给服务端Socket绑定 地址信息结构体
	//绑定地址
	bind(SerSock, (SOCKADDR*)&SerAddr, sizeof(SerAddr);
	//监听  等待连接请求  等待队列
	//第一个参数为服务端的套接字  第二个等待队列的长度 5 (表示最多可以连接五个请求)
	if (listen(SerSock, 5) == -1) {    
		cout << "错误" << WSAGetLastError() << endl;
		closesocket(SerSock);
		WSACleanup();  //关闭
		return -1;
	}

	int len = sizeof(CliAddr);
	//客户端地址信息 绑定一个新的套接字 连接后welcomeSocket会变成新的connectSocket
	//接受连接  如果没连接上就返回-1   accept可能会堵塞
	if ((CliSock = accept(SerSock, (SOCKADDR*)&CliAddr, &len)) == -1) {
		cout << "错误" << WSAGetLastError() << endl;
		closesocket(SerSock);
		WSACleanup();  //关闭
		return -1;
	}

	// Recv 接收它收到的数据   I/O操作
	/*
	第一个参数为 客户端套接字
	第二个参数为 要发送的缓冲区(要接收的信息)
	第三个参数为 缓冲区的大小(你要接收的信息的长度)
	第四个参数为 标志 一般都为0
	*/
	char RecvBuf[BUFSIZ]{};
	int ret=recv(CliSock,RecvBuf,sizeof(RecvBuf),0);
	if (ret <= 0) {
		cout << "错误" << WSAGetLastError() << endl;
		closesocket(SerSock);
		WSACleanup();  //关闭
		return -1;
	}
	cout << "RecvBuf=" << "  " << RecvBuf << endl;
	// Send 发送网络数据   I/O操作
	/*
	第一个参数为 客户端套接字
	第二个参数为 要发送的缓冲区(要发送的信息)
	第三个参数为 缓冲区的大小(你要发送的信息的长度)
	第四个参数为 标志
	*/
	char SendBuf[]{ "hello Client!" };
	ret = send(CliSock, SendBuf, sizeof(SendBuf), 0);
	if (ret <= 0) {
		cout << "错误=" << WSAGetLastError() << endl;
		closesocket(SerSock);
		WSACleanup();  //关闭
		return -1;
	}
	cout << "结束" << endl;
	closesocket(SerSock);
	closesocket(CliSock);
	WSACleanup();

	return 0;
}

 Client:


#include<iostream>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
//void ErrorSocket{};

int main() {
	cout << "开始" << endl;
	WSADATA wsaData{};
	SOCKET sock{};
	sockaddr_in SerAddr{};

	//初始化网络库
	if (WSAStartup(MAKEWORD(2, 1), &wsaData) == -1) {
		cout << "错误" << WSAGetLastError() << endl;
		return -1;
	}
	//创建socket
	if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {  //正常有值
		cout << "错误" << WSAGetLastError() << endl;
		return -1;
	}

	SerAddr.sin_family = PF_INET;
	SerAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //指定客户端地址?
	SerAddr.sin_port = htons(6969);
//与服务端进行连接
	connect(sock, (SOCKADDR*)&SerAddr, sizeof(SerAddr));
	char SendBuf[]{ "Client 你好" };
	send(sock, SendBuf, sizeof(SendBuf), 0);  //发送
	closesocket(sock);
	WSACleanup();
	return 0;
}

UDP Socket编程:

UDP Socket编程

UDP: 在客户端和服务器之间没有连接

  • 发送端在每一个报文中明确地指定目标的IP地址和端口号
  • 服务器必须从收到的分组中提取出发送端的IP地址和端口号

UDP: 传送的数据可能乱序,也可能丢失

UDP 为客户端和服务器提供不可靠的字节组的传送服务

Server:

#include<iostream>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main() {
	WSADATA wsaData{};
	SOCKET sock{};
	sockaddr_in SerAddr{}, CliAddr{};
	if (WSAStartup(MAKEWORD(2, 1), &wsaData) == -1) {
		cout << "错误3:  " << WSAGetLastError() << endl;
		return -1;
	}
	sock = socket(AF_INET, SOCK_DGRAM,0);  //UDP不使用SOCK_STREAM  而是使用SOCK_DGRAM
	if (sock == -1) {
		cout << "有错误4:  " << WSAGetLastError() << endl;
		closesocket(sock);
		WSACleanup();
		return -1;
	}


//服务端名字,IP地址,端口
	SerAddr.sin_family = PF_INET;
	SerAddr.sin_addr.s_addr = inet_addr("0.0.0.0");//本机网络
	SerAddr.sin_port = htons(6969);

//需要绑定地址 bind  UDP的绑定与TCP不同
	if (bind(sock, (SOCKADDR*)&SerAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
		cout << "有错误5:  " << WSAGetLastError() << endl;
		closesocket(sock);
		WSACleanup();
		return -1;
	}

	char RecvBuf[1024]{};
	int len = sizeof(CliAddr);  //客户端传输的信息的长度 
	recvfrom(sock, RecvBuf, sizeof(RecvBuf), 0, (SOCKADDR*)&CliAddr, &len); //接收什么的数据
	cout << "Client Message" <<RecvBuf<< endl;
//传输回去的信息
	char SendBuf[1024]{ "Hello Client" }; 
	sendto(sock, SendBuf, sizeof(SendBuf), 0, (SOCKADDR*)&CliAddr, len);  //发送到什么位置
	cout << "End" << endl;
//需要关闭套接字
	closesocket(sock);
	WSACleanup();
	return 0;


}

Client:

#include<iostream>
#include<windows.h>
#pragma comment (lib,"ws2_32.lib")
using namespace std;
int main() {
	
	WSADATA wsaData{ };
	SOCKET sock{};
	sockaddr_in SerAddr{};
	if (WSAStartup(MAKEWORD(2, 1), &wsaData) == -1) {
		cout << "有错误1:  " << WSAGetLastError() << endl;
		WSACleanup();
		return -1;
	}
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == -1) {
		cout << "有错误2:  " << WSAGetLastError() << endl;
		WSACleanup();
		return -1;
	}

//客户端名字,IP地址,端口
	SerAddr.sin_family = PF_INET;
	SerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	SerAddr.sin_port = htons(6969);

	//连接 检测服务端是否在线
	connect(sock, (SOCKADDR*)&SerAddr, sizeof(SerAddr));

	char SendBuf[]{"Hello Server!-------------------"};
	send(sock, SendBuf, sizeof(SendBuf), 0); //向服务端传输信息
	char RecvBuf[1024]{};   
	recv(sock, RecvBuf, sizeof(RecvBuf), 0);  //接收服务端传输给客户端的信息
	cout << "Server Message:  " << RecvBuf << endl;
	cout << "结束" << endl;
	closesocket(sock);
	WSACleanup();
	getchar();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值