栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux编程基础 7.2:套接字编程-2

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux编程基础 7.2:套接字编程-2

1 网络字节序

大端模式:若将数据的高字节保存在内存的低地址,将数据的低字节保存在内存的高地址;
小端模式:若将数据的高字节保存在内存的高地址,将数据的低字节保存在内存的低地址。

  • 网络数据流:大端模式
  • 计算机:大端/小端模式

Linux系统中提供了一些用于字节序转换的函数,这些函数存在于函数库arpa/inet.h中,它们的定义如下:

uint32_t htonl(uint32_t hostlong);//主机字节序转换为网络字节序(长整型)
uint16_t htons(uint16_t hostshort);//主机字节序转换为网络字节序(短整型)
uint32_t ntohl(uint32_t netlong);//网络字节序转换为主机字节序(长整型)
uint16_t ntohs(uint16_t netshort);//网络字节序转换为主机字节序(短整型)
  • h:主机host;
  • n:网络network;
  • l:32位长整型;
  • s:16位短整型;
  • 若主机使用大端模式,则这些函数不做转换,将参数原样返回;
  • 若主机采用小端模式,参数的字节顺序才会被修改。
2 IP地址转换函数
  • 常见的IP地址格式类似“192.168.10.1”,这是一个标准的IPv4格式的地址,但这种格式是为了方便用户对其进行操作,若要使计算机能够识别,需先将其转换为二进制格式。
  • 如今Linux编程中常用inet_pton()和inet_ntop()来转换IP地址,这两个函数不但能转换IPv4格式的地址in_addr,还能转换IPv6格式的地址in_addr6。
#include 
int inet_pton(int af, const char *src, void *dst);//先将字符串src转换为af地址族中的网络地址结构,再将转换后的网络地址结构存储到参数dst中,af必须为AF_INET或AF_INET
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);//网络地址转换为字符串
3 socket编程实例

【案例 1】编写C/S结构的程序,分别创建服务器和客户端,使用TCP协议实现。

  • 客户端:从终端获取一个字符串发送给服务器,然后接收服务器返回的字符串并打印;
  • 服务器:接收客户端发来的字符,将每个字符转换为大写再返回给客户端。
tcpclient.c
#include 
#include 
#include 
#include 
#include 
#include 
#define MAXLINE 80
#define SERV_PORT 6666
int main(int paraArgc, char *paraArgv[]) {
	struct sockaddr_in tempServAddr;		//定义服务器地址结构体
	char tempBuf[MAXLINE];
	int tempSockFd, tempDataLen;
	char *tempStr;
	if (paraArgc != 2) {
		fputs("usage: ./client messagen", stderr);
		exit(1);
	}//of if
	tempStr = paraArgv[1];
	//创建客户端套接字文件
	tempSockFd = socket(AF_INET, SOCK_STREAM, 0);
	//初始化服务器端口地址
	bzero(&tempServAddr, sizeof(tempServAddr));
	tempServAddr.sin_family = AF_INET;
	inet_pton(AF_INET, "127.0.0.1", &tempServAddr.sin_addr);
	tempServAddr.sin_port = htons(SERV_PORT);
	//请求链接
	connect(tempSockFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));
	//发送数据
	send(tempSockFd, tempStr, strlen(tempStr), 0);
	//接收客户端返回的数据
	tempDataLen = recv(tempSockFd, tempBuf, MAXLINE, 0);
	printf("Response from server:n");
	//将客户端返回的数据打印到终端
	write(STDOUT_FILENO, tempBuf, tempDataLen);
	//关闭连接
	close(tempSockFd);
	return 0;
}//of main

tcpserver.c
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MAXLINE 80							//最大数据长度
#define SERV_PORT 6666						//服务器端口号
int main(void) {
	struct sockaddr_in tempServAddr, tempCliAddr; 	//定义服务器与客户端地址结构体
	socklen_t tempCliAddrLen; 					//客户端地址长度
	int tempListenFd, tempConnFd;
	char tempBuf[MAXLINE];
	char tempStr[INET_ADDRSTRLEN];
	int i, tempDataLen;
	//创建服务器端套接字文件
	tempListenFd = socket(AF_INET, SOCK_STREAM, 0);
	//初始化服务器端口地址
	bzero(&tempServAddr, sizeof(tempServAddr));	//将服务器端口地址清零
	tempServAddr.sin_family = AF_INET;
	tempServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	tempServAddr.sin_port = htons(SERV_PORT);
	//将套接字文件与服务器端口地址绑定
	bind(tempListenFd , (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));
	//监听,并设置最大连接数为20
	listen(tempListenFd , 20);
	printf("Accepting connections ...n");
	//接收客户端数据,并处理请求
	while (1) {
		tempCliAddrLen= sizeof(tempCliAddr);
		tempConnFd = accept(tempListenFd, (struct sockaddr *)&tempCliAddr, &tempCliAddrLen);
		tempDataLen = recv(tempConnFd, tempBuf, MAXLINE, 0);
		printf("received from %s at PORT %dn",
			inet_ntop(AF_INET, &tempCliAddr.sin_addr, tempStr, sizeof(tempStr)),
			ntohs(tempCliAddr.sin_port));
		for (i = 0; i < tempDataLen; i++){
			tempBuf[i] = toupper(tempBuf[i]);
		}//of for i
		send(tempConnFd, tempBuf, tempDataLen, 0);
		//关闭连接
		close(connfd);
	}//of while
	return 0;
}//of main

【案例2】编写C/S结构的程序,分别创建服务器和客户端,使用UDP协议实现。

  • 客户端:从终端获取一个字符串发送给服务器,然后接收服务器返回的字符串并打印;
  • 服务器:接收客户端发来的字符,将每个字符转换为大写再返回给客户端。
udpclient.c
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MAXLINE 80
#define SERV_PORT 6666
int main(int paraArgc, char *paraArgv[]){
	struct sockaddr_in tempServAddr;
	int tempSockFd, tempDataLen;
	char tempBuf[MAXLINE];
	tempSockFd = socket(AF_INET, SOCK_DGRAM, 0);
	bzero(&tempServAddr, sizeof(tempServAddr));
	tempServAddr.sin_family = AF_INET;
	inet_pton(AF_INET, "127.0.0.1", &tempServAddr.sin_addr);
	tempServAddr.sin_port = htons(SERV_PORT);
	//发送数据到客户端
	while (fgets(tempBuf, MAXLINE, stdin) != NULL) {
		tempDataLen = sendto(tempSockFd, tempBuf, strlen(tempBuf), 0, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));
		if (tempDataLen == -1) {
			perror("sendto error");
		}//of if
		//接收客户端返回的数据
		tempDataLen = recvfrom(tempSockFd, tempBuf, MAXLINE, 0, NULL, 0);
		if (tempDataLen == -1){
			perror("recvfrom error");
		}//of if
		//将接收到的数据打印到终端
		send(STDOUT_FILENO, tempBuf, tempDataLen , 0);
	}//of while
	close(tempSockFd);
	return 0;
}//of main

udpserver.c
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MAXLINE 80							//最大数据长度
#define SERV_PORT 6666						//服务器端口号
int main(void) {
	struct sockaddr_in tempServAddr, tempCliAddr;	//定义服务器与客户端地址结构体
	socklen_t tempCliAddrLen;					//客户端地址长度
	int tempSockFd;								//服务器socket文件描述符
	char tempBuf[MAXLINE];
	char tempStr[INET_ADDRSTRLEN];
	int i, tempDataLen;
	tempSockFd = socket(AF_INET, SOCK_DGRAM, 0);//创建服务器端套接字文件
	//初始化服务器端口地址
	bzero(&tempServAddr, sizeof(tempServAddr));	//地址结构体清零
	tempServAddr.sin_family = AF_INET;			//指定协议族
	tempServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	tempServAddr.sin_port = htons(SERV_PORT);	//指定端口号
	//绑定服务器端口地址
	bind(tempSockFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));
	printf("Accepting connections ...n");
	//数据传输
	while (1) {
		tempCliAddrLen = sizeof(tempCliAddr);
		//接收数据
		tempDataLen = recvfrom(tempSockFd, tempBuf, MAXLINE, 0, (struct sockaddr*)&tempCliAddr, &tempCliAddrLen);
		if (tempDataLen == -1){
			perror("recvfrom error");
		}//of if
		printf("received from %s at PORT %dn",
			inet_ntop(AF_INET, &tempCliAddr.sin_addr, tempStr, sizeof(tempStr)),
			ntohs(tempCliAddr.sin_port));
		//服务器端操作,小写转大写
		for (i = 0; i < tempDataLen; i++){
			buf[i] = toupper(buf[i]);
		}//of for i
		tempDataLen = sendto(tempSockFd, tempBuf, tempDataLen, 0, (struct sockaddr *)&tempCliAddr, sizeof(tempCliAddr));
		if (tempDataLen == -1){
			perror("sendto error");
		}//of if
	}//of while
	close(tempSockFd);
	return 0;
}//of main
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/884760.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号