Linux系统编程(5)——网络编程

一、TCP/UDP对比

  1. TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前 不需 要建立连接
  2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
  3. TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
  4. UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
  5. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
  6. TCP首部开销20字节;UDP的首部开销小,只有8个字节
  7. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

二、端口号作用

  1. 一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等
  2. 这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。
  3. 实际上是通过“IP地址+端口号”来区 分不同的服务的。
  4. 端口提供了一种访问通道,服务器一般都是通过知名端口号来识别的。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TFTP(简单文件传送协议)服务器的UDP端口号都是69。

三、字节序

  1. Little endian 小端字节序:低字节存储在起始地址。
  2. Big endian 大端字节序:高字节存储在起始地址。
  3. 网络字节序=大端字节序

四、字节序转换api

#include <netinet/in.h>

uint16_t htons(uint16_t host16bitvalue);    
//返回网络字节序的值uint32_t 

htonl(uint32_t host32bitvalue);    
//返回网络字节序的值uint16_t 

ntohs(uint16_t net16bitvalue);     
//返回主机字节序的值uint32_t 

ntohl(uint32_t net32bitvalue);     
//返回主机字节序的值
  • h代表host,n代表net,s代表short(两个字节),l代表long(4个字节),通过上面的4个函数可以实现主机字节序和网络字节序之间的转换。有时可以用INADDR_ANY,INADDR_ANY指定地址让操作系统自己获取。

五、Sockt服务器和客户端的开发步骤

  1. 创建套接字
  2. 为套接字添加信息(IP地址和端口号)
  3. 监听网络连接
  4. 监听到有客户端接入,接受一个连接
  5. 数据交互
  6. 关闭套接字,断开连接
    在这里插入图片描述

六、相关函数原型

  1. int socket(int domain, int type, int protocol);
    在这里插入图片描述
  2. bind()函数
    在这里插入图片描述在这里插入图片描述
  3. 地址转换API
    int inet_aton(const char* straddr,struct in_addr *addrp);
    //把字符串形式的“192.168.1.123”转为网络能识别的格式
    
    char* inet_ntoa(struct in_addr inaddr); 
    //把网络格式的ip地址转为字符串形式
    
  4. 监听listen()函数 在这里插入图片描述
  5. 连接accept()函数 在这里插入图片描述
  6. 数据收发函数
    在这里插入图片描述
  7. 数据收发常用第二套API
    在这里插入图片描述
  8. 客户端的connect函数
    在这里插入图片描述

七、客户端接入服务器进行聊天

sever.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
	int s_fd, c_fd;
	int c_size;
	char readbuf[128];
	char msg[128];
	struct sockaddr_in s_addr;	
	struct sockaddr_in c_addr;
	memset(msg, 0, sizeof(msg));
	memset(readbuf, 0, sizeof(readbuf));
	//1. socket
	s_fd = socket(AF_INET, SOCK_STREAM, 0);
//	if(s_fd == -1){
//		perror("socket");
//		exit(-1);
//	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(8080);
	inet_aton("192.168.101.72",&s_addr.sin_addr);

	bind(s_fd, (struct sockaddr *)&s_addr , sizeof(struct sockaddr_in));

	listen(s_fd, 10);

	while(1) {
		c_size =sizeof(struct sockaddr_in);
		c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &c_size);

		if(c_fd != -1) {
			if(fork() == 0) {
				printf("connect, clint ip = %s\n", inet_ntoa(c_addr.sin_addr));
	
				while(1) {
					memset(readbuf, 0, sizeof(readbuf));
					memset(msg, 0, sizeof(msg));
					int n_read = read(c_fd, readbuf, 20);
					if(n_read != -1) {
						printf("readbuf = %s, n_read = %d\n", readbuf, n_read);
					}

					printf("input :\n");
					gets(msg);
					write(c_fd, msg, strlen(msg));
				}
			}
		}

	}
	return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
	int s_fd;
	char readbuf[128];
	char msg[128];
	struct sockaddr_in s_addr;	
	memset(msg, 0, sizeof(msg));
	memset(readbuf, 0, sizeof(readbuf));
	//1. socket
	s_fd = socket(AF_INET, SOCK_STREAM, 0);
//	if(s_fd == -1){
//		perror("socket");
//		exit(-1);
//	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(8080);
	inet_aton("192.168.101.72",&s_addr.sin_addr);

	int c_ret =  connect(s_fd, (struct sockaddr *) &s_addr, sizeof(struct sockaddr));

	if(c_ret == -1) {
		perror("client error");
		exit(-1);
	}

	while(1) {
		memset(msg, 0, sizeof(msg));
		memset(readbuf, 0, sizeof(readbuf));
		printf("clientt input :\n");
		gets(msg);
		write(s_fd, msg, strlen(msg));
	
		read(s_fd, readbuf, 128);
		printf("client readbuf = %s\n", readbuf);	
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值