Linux内核中已经把TCP/UDP封装在了协议栈中,从编程的角度来说,就是如何使用这些协议栈的问题了,其中,Linux提供了一种叫socket的特殊文件,其实也是一种特殊的操作系统接口,通过这个接口,我们可以利用Linux内核中的协议栈,因此,对编程来说就会变得比较容易,使用UDP或者TCP仅仅是函数接口传递的参数不同而已,大部分的代码是相同的,自己实现的基于UDP的客户端--服务器如下:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <arpa/inet.h>
-
-
/***********************************************************
-
* 函数功能:基于UDP实现简单的客户端服务器,客户端给服务器发
-
* 数据,服务器负责接收数据并把数据打印在终端。
-
* 服务器端实现的基本步骤:
-
* 1. 创建套接字
-
* 2. 给套接字绑定服务器的端口和IP地址
-
* 3. 监听套接字
-
* 4. 接收客户端发送的数据
-
***********************************************************/
-
-
//./server ip port
-
int main(int argc, const char *argv[])
-
{
-
int n;
-
int sockfd;
-
char buf[1024];
-
struct sockaddr_in server_addr;
-
struct sockaddr_in peer_addr;
-
socklen_t addrlen = sizeof(struct sockaddr);
-
-
if(argc < 3)
-
{
-
fprintf(stderr,"Usage : %s \n",argv[0]);
-
exit(EXIT_FAILURE);
-
}
-
-
//1. 创建套接字
-
sockfd = socket(AF_INET,SOCK_DGRAM,0);
-
if(sockfd < 0){
-
perror("Fail to socket");
-
exit(EXIT_FAILURE);
-
}
-
-
//2. 给套接字绑定服务器的端口和IP地址
-
server_addr.sin_family = AF_INET;
-
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
-
server_addr.sin_port = htons(atoi(argv[2]));
-
//3. 监听套接字,实质上是在等待是否有客户端对该套接字进行请求
-
if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
-
{
-
perror("Fail to bind");
-
exit(EXIT_FAILURE);
-
}
-
-
while(1)
-
{
-
// 4. 接收客户端发送的数据,其中第三个参数可以获取客户端的端口和IP地址信息
-
n = recvfrom(sockfd,buf,sizeof(buf) - 1,0,(struct sockaddr *)&peer_addr,&addrlen);
-
buf[n] = '\0';
-
-
//在服务器端打印客户端发送的数据、客户端的端口、IP地址
-
printf("-----------------------------\n");
-
printf("Port : %d\n",ntohs(peer_addr.sin_port));
-
printf("Ip : %s\n",inet_ntoa(peer_addr.sin_addr));
-
printf("buf : %s\n",buf);
-
printf("-----------------------------\n");
-
}
-
-
-
return 0;
-
}
客户端实现代码如下:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <arpa/inet.h>
-
-
/***********************************************************
-
* 函数功能:基于UDP实现简单的客户端服务器,客户端给服务器发
-
* 数据,服务器负责接收数据并把数据打印在终端。
-
* 客户端实现的基本步骤:
-
* 1. 创建套接字
-
* 2. 给套接字绑定服务器的端口和IP地址
-
* 3. 给服务器发送数据
-
***********************************************************/
-
//./client ip port
-
int main(int argc, const char *argv[])
-
{
-
int n;
-
int sockfd;
-
char buf[1024];
-
struct sockaddr_in server_addr;
-
struct sockaddr_in client_addr;
-
struct sockaddr_in peer_addr;
-
socklen_t addrlen = sizeof(struct sockaddr);
-
-
//输入参数检查
-
if(argc < 3)
-
{
-
fprintf(stderr,"Usage : %s \n",argv[0]);
-
exit(EXIT_FAILURE);
-
}
-
-
//创建套接字,注意第二个参数必须是SOCK_DGRAM
-
sockfd = socket(AF_INET,SOCK_DGRAM,0);
-
if(sockfd < 0){
-
perror("Fail to socket");
-
exit(EXIT_FAILURE);
-
}
-
-
//填充服务器的端口和IP地址,因为要给别的服务器发生数据,至少需要知道两个参数:端口和IP
-
server_addr.sin_family = AF_INET;
-
server_addr.sin_addr.s_addr = inet_addr(argv[1]);//填充的IP地址必须转化为网络字节序
-
server_addr.sin_port = htons(atoi(argv[2]));
-
-
//完成从标准输入读取字符,然后发送给服务器。
-
while(1)
-
{
-
printf("input >");
-
fgets(buf,sizeof(buf),stdin); //按行读取,包括'\n'
-
buf[strlen(buf) - 1] = '\0'; //把读入的'\n'用'\0'替换,保证buf中的字符串是以'\0'结尾
-
-
//客户端给服务器发送数据,第三个参数表示服务器的地址
-
n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&server_addr,addrlen);
-
if(n < 0){
-
perror("Fail to sendto");
-
exit(EXIT_FAILURE);
-
}
-
}
-
-
return 0;
-
}
测试结果如下:
-
ubuntu@ubuntu:~/network/udp/udp/server$ ./server 192.168.127.131 8888
-
-----------------------------
-
Port : 59438
-
Ip : 192.168.127.131
-
Buf : hi
-
-----------------------------
-
-----------------------------
-
Port : 59438
-
Ip : 192.168.127.131
-
Buf : i am client
-
-----------------------------
-
ubuntu@ubuntu:~/network/udp/udp/client$ vi client.c
-
ubuntu@ubuntu:~/network/udp/udp/client$ ./client 192.168.127.131 8888
-
input >hi
-
input >i am client
-
input >
阅读(1398) | 评论(0) | 转发(0) |