Linux网络编程【二】:UDP socket套接字详解

与TCP socket一致,基于UDP socket(无连接)编程分服务器端和客户端

服务器端过程:1.创建套接字(socket)2.将套接字绑定到一个本地地址和端口上(bind)3.用返回的套接字和客户端进行通信(recvfrom)4.返回,等待另一个客户请求。5.关闭套接字。

客户端过程:1.创建套接字(socket)2.和服务器端进行通信(sendto)3.关闭套接字

而与TCP不同的是:

(1)socket函数中type类型SOCK_DGRAM是一种无连接的Socket,对应于无连接的UDP服务应用

(2)使用了两种函数recvfrom和sendto

recvfrom函数::本函数用于从(已连接)套接口上接收数据,并捕获数据发送源的地址


sockfd:标识一个已连接套接口的描述字。
buf:接收数据缓冲区。
len:缓冲区长度。
flags:调用操作方式。
src_addr:(可选)指针,指向装有源地址的缓冲区。——输出型参数
addrlen:(可选)指针,指向from缓冲区长度值。——输入输出型参数。
返回值为整型,如果成功,则返回接收到的字节数,失败则返回SOCKET_ERROR。


sendto函数:指向一指定目的地发送数据,sendto()适用于发送未建立连接的UDP数据包


返回值为整型,如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。
sockfd: 套接字
buf: 待发送数据的缓冲区
len: 缓冲区长度
flags:调用方式标志位, 一般为0, 改变Flags,将会改变Sendto发送的形式:阻塞
addr:(可选)指针,指向目的套接字的地址
addr:lenaddr所指地址的长度


具体实现代码:

服务器端:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>

static void usage(const char* proc)
{
	printf("%s [ip] [port]", proc);
}

int main(int argc,char* argv[])
{
	if(argc != 3)
	{
		usage(argv[0]);
		return 0;
	}

	int sock = socket(AF_INET, SOCK_DGRAM, 0);

	if(sock < 0)
	{
		perror("socket");
		return 2;
	}

	struct sockaddr_in local;
	local.sin_family = AF_INET;
	local.sin_port = htons(atoi(argv[2]));
	local.sin_addr.s_addr = inet_addr(argv[1]);

	if(bind(sock, (struct sockaddr *)&local, sizeof(local)) < 0)
	{
		perror("bind");
		return 3;
	}

	char buf[1024];
    struct sockaddr_in client;
	socklen_t len = sizeof(client);

	while(1)
	{
		ssize_t s = recvfrom(sock, buf, sizeof(buf)-1, 0, (struct sockaddr*)&client, &len);
		if(s > 0)
		{
			buf[s] = 0;
			printf("%s : %d say# %s\n", inet_ntoa(client.sin_addr),ntohs(client.sin_port),buf);
			ssize_t _s = sendto(sock, buf, sizeof(buf), 0, (struct sockaddr*)&client, len);
		}
	}
	close(sock);
	return 0;
}

客户端:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>

static void usage(const char* proc)
{
	printf("%s [ip] [port]\n",proc);
}

int main(int argc, char* argv[])
{
	if(argc != 3)
	{
		usage(argv[0]);
		return 1;
	}

	int sock = socket(AF_INET, SOCK_DGRAM, 0);
	if(sock < 0)
	{
		perror("socket");
		return 2;
	}

	struct sockaddr_in peer;
	peer.sin_family = AF_INET;
	peer.sin_port = htons(atoi(argv[2]));
	peer.sin_addr.s_addr = inet_addr(argv[1]);

	char buf[1024];
	while(1)
	{
		printf("Please Enter :");
		fflush(stdout);

		ssize_t s = read(0, buf, sizeof(buf)-1);
		if(s > 0)
		{
			buf[s] = 0;
			sendto(sock, buf, sizeof(buf), 0, (struct sockaddr*)&peer, sizeof(peer));
			ssize_t _s = recvfrom(sock, buf, sizeof(buf)-1, 0, NULL, NULL);
			printf("server echo# : %s\n", buf);
		}
		else if(s == 0)
		{
			printf("client quit...");
		}
	}
	close(sock);
	return 0;
}


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值