Linux下socket编程之UDP简单实现

本文实现一个简单的UDP小例子,来说明Linux下socket编程之UDP的简单实现。本文主要包括三个部分:服务器端的实现,客服端的实现和通信测试。实现的功能:客服端发送一条消息给服务器端,服务器端把客服端发来的消息给显示出来。

一、服务器端的实现

1、打开一个socket用户服务器

/* 1、打开一个socket */
iSocketServerFd = socket(AF_INET, SOCK_DGRAM, 0);	// 网路类型为ipv4,链接类型为udp
2、将上面打开的socket与服务器进行绑定

/* 2、绑定 */
/* 2.1 设置要绑定的服务器端 */
tSocketServerAddr.sin_family      = AF_INET;			// 网络类型为ipv4
tSocketServerAddr.sin_port        = htons(SOCKET_PORT);	// 设置服务器端口
tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);	
memset(tSocketServerAddr.sin_zero, 0, 8);

iSockAddrLen = sizeof(struct sockaddr);

/* 2.2 对服务器端进行绑定 */
iRet = bind(iSocketServerFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
3、接收客服端发送过来的数据

/* 3、接收数据 */
iRecvLen = recvfrom(iSocketServerFd, ucRecvBuf, ARRAY_LENGTH, 0,
                    (struct sockaddr *)&tSocketClientAddr, &iSockAddrLen);
服务器端实现的完整代码如下所示:
#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include 
#include 


#define SOCKET_PORT		1234		// 定义socket绑定的端口
#define LISTEN_BACKLOG	10			// 设置服务器最大的监听数量
#define ARRAY_LENGTH	256			// 定义缓冲区的大小

/* 
 * 接收客服端发送过来的数据,并把它们打印出来
 */
int main(void)
{
	int iSocketServerFd;	// 定义服务器端的socket文件描述符
	int iSocketClientFd;	// 定义客服端的socket文件描述符

	struct sockaddr_in tSocketServerAddr;	
	struct sockaddr_in tSocketClientAddr;

	int iSockAddrLen;	
	int iRet;

	unsigned char ucRecvBuf[ARRAY_LENGTH];	// 定义接收缓冲区
	int iRecvLen;

	signal(SIGCHLD,SIG_IGN); 

	/* 1、打开一个socket */
	iSocketServerFd = socket(AF_INET, SOCK_DGRAM, 0);	// 网路类型为ipv4,链接类型为udp
	if(iSocketServerFd == -1)
	{
		printf("socket error!\n");
		return -1;
	}

	/* 2、绑定 */
	/* 2.1 设置要绑定的服务器端 */
	tSocketServerAddr.sin_family      = AF_INET;			// 网络类型为ipv4
	tSocketServerAddr.sin_port        = htons(SOCKET_PORT);	// 设置服务器端口
	tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);	
	memset(tSocketServerAddr.sin_zero, 0, 8);

	iSockAddrLen = sizeof(struct sockaddr);

	/* 2.2 对服务器端进行绑定 */
	iRet = bind(iSocketServerFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
	if(iRet == -1)
	{
		printf("bind error!\n");
		return -1;
	}

	while(1)
	{
		/* 3、接收数据 */
		iRecvLen = recvfrom(iSocketServerFd, ucRecvBuf, ARRAY_LENGTH, 0,
                        (struct sockaddr *)&tSocketClientAddr, &iSockAddrLen);
		if(iRecvLen <= 0)	// 失败
		{
			printf("recvfrom error!\n");
			close(iSocketServerFd);
			return -1;
		}
		else	// 成功,将接收到的数据打印出来
		{
			ucRecvBuf[iRecvLen] = '\0';
			printf("Receive a message from : %s\n", inet_ntoa(tSocketClientAddr.sin_addr));
			printf("The message is : %s\n", ucRecvBuf);
		}
	}

	close(iSocketServerFd);
	return 0;
}


二、客服端的实现
客服端的实现总体上来说分为两种方式:一种是先和服务器端进行链接然后在进行通信,另一种是直接进行通信。

2.1 先连接再通信

a、打开一个socket用于客服端

/* 1、打开一个socket用于客服端 */
iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);
b、连接

/* 2、connect */
/* 2.1 设置链接的服务器端的基本信息 */
tSocketServerAddr.sin_family      = AF_INET;			// 网络类型为ipv4
tSocketServerAddr.sin_port        = htons(SOCKET_PORT);	// 服务器端的网络端口
iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr);	// 客服端的ip地址
if(iRet == 0)
{
	printf("server ip is not valid!\n");
	return -1;
}
memset(tSocketServerAddr.sin_zero, 0, 8);

iSockAddrLen = sizeof(struct sockaddr);

/* 2.2 将服务器端和客服端链接起来 */
iRet = connect(iSocketClientFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
c、发送数据

/* 3、将用户的输入发送给服务器端 */
iSendLen = send(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0);
完整的代码如下:
#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include 

#define SOCKET_PORT		1234	// 设置服务器端的端口
#define ARRAY_LENGTH	256		// 设置缓冲区的大小

/*
 *	输入一个字符串,发送给服务器端
 */
int main(int argc, char **argv)
{
	int iSocketClientFd;	// 描述客服端socket的文件描述符

	struct sockaddr_in tSocketServerAddr;

	int iSockAddrLen;
	int iSendLen;
	unsigned char ucSendBuf[ARRAY_LENGTH];	// 定义一个缓冲区
	int iRet;

	if(argc != 2)
	{
		printf("Usage :\n");
		printf("%s \n", argv[0]);
		return -1;
	}

	/* 1、打开一个socket用于客服端 */
	iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);
	if(iSocketClientFd == -1)
	{
		printf("socket error!\n");
		return -1;
	}

	/* 2、connect */
	/* 2.1 设置链接的服务器端的基本信息 */
	tSocketServerAddr.sin_family      = AF_INET;			// 网络类型为ipv4
	tSocketServerAddr.sin_port        = htons(SOCKET_PORT);	// 服务器端的网络端口
	iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr);	// 客服端的ip地址
	if(iRet == 0)
	{
		printf("server ip is not valid!\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);

	iSockAddrLen = sizeof(struct sockaddr);

	/* 2.2 将服务器端和客服端链接起来 */
	iRet = connect(iSocketClientFd, (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
	if(iRet == -1)
	{
		printf("connect error!\n");
		return -1;
	}

	printf("Input a message to %s: \n", argv[1]);
	while(1)
	{
		if(fgets(ucSendBuf, ARRAY_LENGTH, stdin))	// 接收用户的输入
		{
			/* 3、将用户的输入发送给服务器端 */
			iSendLen = send(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0);
			if(iSendLen <= 0)
			{
				printf("send error!\n");
				close(iSocketClientFd);
				return -1;
			}
		}
	}

	close(iSocketClientFd);
	return 0;
}

2.2 直接进行通信
a、打开socket

/* 1、打开客服端的socket */
iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);	// 网络类型为ipv4, 传输类型为udp
b、发送数据

/* 2、强用户端的输入发送给服务器端 */
iSendLen = sendto(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0,
               (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
完整的代码实现如下:
#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include 

#define SOCKET_PORT		1234	// 设置服务器端的网络端口
#define ARRAY_LENGTH	256		// 设置缓冲区的大小

/*
 *	从用户端输入一个字符串,并把这个字符串发送给客服端
 */
int main(int argc, char **argv)
{
	int iSocketClientFd;	// 定义一个表示客服端socket的文件描述符

	struct sockaddr_in tSocketServerAddr;

	int iSockAddrLen;
	int iSendLen;
	unsigned char ucSendBuf[ARRAY_LENGTH];	// 定义缓冲区
	int iRet;

	if(argc != 2)
	{
		printf("Usage :\n");
		printf("%s \n", argv[0]);
		return -1;
	}

	/* 1、打开客服端的socket */
	iSocketClientFd = socket(AF_INET, SOCK_DGRAM, 0);	// 网络类型为ipv4, 传输类型为udp
	if(iSocketClientFd == -1)
	{
		printf("socket error!\n");
		return -1;
	}

	/* 设置要链接的服务器端的基本信息 */
	tSocketServerAddr.sin_family      = AF_INET;			// 网络类型为ipv4
	tSocketServerAddr.sin_port        = htons(SOCKET_PORT);	// 服务器端的网络端口
	iRet = inet_aton(argv[1], &tSocketServerAddr.sin_addr);	// 要连接的客服端的ip地址
	if(iRet == 0)
	{
		printf("server ip is not valid!\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);

	iSockAddrLen = sizeof(struct sockaddr);

	printf("Input a message to %s: \n", argv[1]);
	while(1)
	{
		if(fgets(ucSendBuf, ARRAY_LENGTH, stdin))	// 接收用户端的输入
		{
			/* 2、强用户端的输入发送给服务器端 */
			iSendLen = sendto(iSocketClientFd, ucSendBuf, strlen(ucSendBuf), 0,
                      (const struct sockaddr *)&tSocketServerAddr, iSockAddrLen);
			if(iSendLen <= 0)
			{
				printf("sendto error!\n");
				close(iSocketClientFd);
				return -1;
			}
		}
	}

	close(iSocketClientFd);
	return 0;
}

三、测试
将上面两种方式实现的客服端都和服务器进行通信测试。服务器端和客服端可以在同一台电脑上也可以在不同的电脑上(必须在同一局域网当中),本文是在同一台电脑上对客服端和服务器端进行测试,测试结果如下:

客服端一:



客服端二:



服务器端:

Linux下socket编程之UDP简单实现_第1张图片

从上面结果可以看出,服务器和两个客服端都通信成功。


你可能感兴趣的:(Linux系统编程)