Linux网络编程 2 写一个udp服务器,实现字母的大小写转换(附udp和tcp服务器的区别)

服务器端:udp_ser.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>

/*
udp:用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单的不可靠信息的传送服务
tcp:传输控制协议,基于字节流的传输层通信协议。面向连接,可靠

udp服务端的C/S模型:
1)、socket()  创建套接字
2)、bind()
3)、listen()   设置监听上限

相比于TCP服务器,udp服务器有如下变化:
dup服务器中,没有监听套接字
1)、socket()函数中,第二个参数:SOCK_STREAM(流式)--》SOCK_DGRAM(报式) 
2)、
listen()函数,严格意义上说,是用来指定客户端同时和服务器三次握手的数量,在UDP中没有三次捂手,可以不写。
同理,由于没有三次捂手,服务器端的accept()函数和客户端的connect()都不需要使用
在网络中,函数read()、write()只能用在TCP中,不能用在UDP中。在UDP中,可以使用函数recefrom()和sendto()。
函数recefrom()同时包含accept()的功能,传出(对端)的地址结构,sendto()同时也包含connect()的功能。

*/
#define SER_PORT   6781
void sys_err(const char *str)
{
	perror(str);
	exit(1);
}
int main (int argc,char *argv[])
{
	int cfd;
	int ret = 0,i; 
	char buf[1024]={0},cli_buf[1024]={0};
	struct sockaddr_in ser_addr,cli_addr;
	socklen_t cli_addr_len;
	cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1) sys_err("socket fail \n");
	/*地址结构*/
	ser_addr.sin_family      = AF_INET;
	ser_addr.sin_port        = htons(SER_PORT);
	ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	ret = bind(cfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
	if(ret == -1)  sys_err("bind fail \n");
	cli_addr_len = sizeof(cli_addr);
	/*循环进行服务器的相关操作 */
	while(1)
	{
		ret = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&cli_addr,&cli_addr_len);
		/*打印客户端ip和端口号*/
		printf("client ip=%s,端口号=%d \n",inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr,cli_buf,sizeof(cli_buf)),
			ntohs(cli_addr.sin_port));
		/*对数据进行处理*/
		for(i=0;i<ret;i++)   buf[i] = toupper(buf[i]);
		/*将转化以后的数据写回去*/
		sendto(cfd,buf,ret,0,(struct sockaddr *)&cli_addr,cli_addr_len);
	}
	close(cfd);
	return 0;
}

客户端:udp_cli.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define  SER_PORT 6781
void sys_err(const char *str)
{
	perror(str);
	exit(1);
}
int main (int argc,char *argv[])
{
	int cfd;
	int ret = 0;
	char buf[1024]={0};
	struct sockaddr_in ser_addr,cli_addr;
	cfd = socket(AF_INET,SOCK_DGRAM,0);
	if(cfd == -1) sys_err("socket fail\n");
	/*地址结构*/
	ser_addr.sin_family      = AF_INET;
	ser_addr.sin_port        = htons(SER_PORT);
	inet_pton(AF_INET,"127.0.0.1",&ser_addr.sin_addr);

	/*发送数据*/
	while(1)
	{
		/*从标准输入得到数据,放入buf。此时,函数sendto()应该用strlen(buf),而不是sizeof(buf)*/
		fgets(buf,sizeof(buf),stdin);
		sendto(cfd,buf,strlen(buf),0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
		/*为了效果更明显*/
		sleep(1);
		/*因为不需要服务器的地址结构了,所以用NULL*/
		ret = recvfrom(cfd,buf,strlen(buf),0,NULL,0);
		/*重定向,显示在屏幕*/
		write(STDOUT_FILENO,buf,ret);
	}
	close(cfd);
	return 0;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

One Piece&

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

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

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

打赏作者

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

抵扣说明:

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

余额充值