基于c++的C/S网络通信 从入门到精通(五)

前面我们使用TCP实现C/S通信

接下来,我们将使用UDP

使用UDP实现数据的收发,我们不用区分客户端和服务器(客户端和服务器端集合在一起)

 

写代码中存在的陷阱:

1.发送和接收的SOCKET 需要单独设置。发送SOCKET 为对方IP,接受SOCKET为本机IP

2.端口绑定,只需要对接受端进行端口绑定

3.sendto发送数据的大小需要使用strlen()而不能使用sizeof(),防止出现发送无用数据

4.recvfrom接受数据的大小使用sizeof(),因为此时strlen(buf)的大小为0,不可使用

5.recvfrom注意接受数据buf的长度,若小于数据的长度,会返回-1

 

#include <iostream>
#include <winsock2.h>
#pragma comment (lib,"WS2_32.lib")

#define SERVER_IP     "127.0.0.1"                   /*  接受方PC主机的IP地址      */
#define SERVER_PORT   (8000)                            /*  PC主机的IP端口      */

SOCKET clientsocket;
SOCKET serversocket;
SOCKADDR_IN  client_addr;
SOCKADDR_IN  server_addr;

DWORD WINAPI SendFun(LPVOID)
{
	clientsocket = socket(AF_INET, SOCK_DGRAM, 0);
	client_addr.sin_family = AF_INET;
	client_addr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);			//接受方IP
	client_addr.sin_port = htons(SERVER_PORT);

	/*同一台电脑端口只能绑定一次,否则无法和自己通信
	bind(clientsocket, (SOCKADDR *)&client_addr, sizeof(client_addr));*/

	char buf[100] = "";
	while (1)
	{
		memset(buf, 0, 100);
		scanf("%s", buf);

		//使用strlen发送实际数据长度
		int ret = sendto(clientsocket, buf, strlen(buf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
		if (ret < 0) {
			printf("send data error");
		}
		Sleep(100);
	}
	return 0;
}

DWORD WINAPI RevFun(LPVOID)
{
	int len = sizeof(SOCKADDR);
	serversocket = socket(AF_INET, SOCK_DGRAM, 0);
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);			//监听本地端口的IP
	server_addr.sin_port = htons(SERVER_PORT);
	bind(serversocket, (SOCKADDR *)&server_addr, sizeof(server_addr));//监听本地端口的IP

	char buf[100] = "";
	while (1)
	{
		memset(buf, 0, 100);
		
		//如果接收到数据的大于buf,ret返回值为-1
		int ret = recvfrom(serversocket, buf, sizeof(buf), 0, (SOCKADDR *)&server_addr, &len);
		if (ret < 0) {
			printf("recv data error");
		}

		printf("%d\n%s\n", ret, buf);
		Sleep(100);
	}
	return 0;
}

int main(int argc, char *argv[])
{
	WSADATA wsadata;
	WSAStartup(MAKEWORD(2, 2), &wsadata);

	HANDLE Send_Thread = CreateThread(NULL, 0, SendFun, 0, 0, NULL);
	HANDLE Rev_Thread = CreateThread(NULL, 0, RevFun, 0, 0, NULL);

	WaitForSingleObject(Rev_Thread, INFINITE);
	WSACleanup();
	return 0;
}

 

目录 (1)基本网络编程实例 Winsock实现网络聊天室【\chap1\ChatRoom(Winsock)】 CSocket实现聊天室【\chap1\ChatRoom(Csocket)】 (2)本地计算机网络编程实例 获取计算机的名称和IP地址【\chap2\Local】 获取计算机的子网掩码【\chap2\ Local】 获取计算机的DNS设置【\chap2\ Local】 获取计算机的网卡地址【\chap2\ Local】 获取计算机安装的协议【\chap2\ Local】 获取计算机提供的服务【\chap2\ Local】 获取计算机的所有网络资源【\chap2\ Local】 修改本地计算机的所有网络设置【\chap2\ Local】 获取计算机TCP/IP协议的所有信息【\chap2\ Local】 (3)局域网网络通信编程实例 获取网上邻居【\chap3\Neighbor】 lIP地址和计算机名之间的转换【\chap3\Neighbor】 l映射网络驱动器【\chap3\Neighbor】 l消息发送程序Net Send【\chap3\Neighbor】 l获取局域网内其他计算机的信息【\chap3\ NeighborInfo】 (4)IE编程实例 简单的浏览器的实现【\chap4\MyBrowser】 删除IE相关历史记录【\chap4\DelHistory】 将应用程序加入到IE工具栏【\chap4\AddToToolBar】 超级链接的实现【\chap4\HyperLink】 禁止IE的弹出窗口【\chap4\StopPopup】 禁止浏览某些网站【\chap4\StopTravel】 IE收藏夹【\chap4\ MyBrowser】 创建桌面快捷方式和活动桌面【\chap4\ShortCut】 (5)基本网络编程实例 点对点文件传输【\chap5\Transfer】 大型文件传输【\chap5\Transfer】 端口扫描程序【\chap5\ MyPortScanner】 Finger编程【\chap5\MyFinger】 Sniff编程【\chap5\MySniff】 Internet文件下载【\chap5\ InternetDownload】 (6)网络通信协议编程 FTP协议【\chap6\FTP】 Email协议【\chap6\Email】 ICMP协议【\chap6\ICMP】 RAS协议【\chap6\RAS】 TAPI协议【\chap6\TAPI】 Telnet协议【\chap6\Telnet】 HTTP协议 【\chap6\HTTP】 (7)Modem /串口通信编程 Modem编程【\chap7\Modem】 MSCOMM控件编程【\chap7\MSCOMM】 串口通信API编程【\chap7\MySerialCom】 (8)代理服务器编程实例 Socks 5协议编程【\chap8\Socks5】 HTTP代理服务器【\chap8\HTTP代理服务】 (9)高级网络通信编程实例 串口通信编程实例【\chap9\SerialPort】 网络流量监控【\chap9\NetTraffic】 网站下载【\chap9\ Snag】 网络子棋系统【\chap9\FiveChess】 语音聊天【\chap9\ ChatRoom】 远程监控【\chap9\RemoteControl】 赠送实例 类似网络蚂蚁的断点续传程序【\Appendix\NetAnts】 网络多播程序【\Appendix\BroadCast】 界面美观的文字聊天程序【\Appendix\Chat】 语音电话【\Appendix\PhoneCall】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值