关于linux编程——网络编程2
一、TCP客户端向服务器上传一个文件
tcp c/s
客户端:
socket
connect
//通信
//1.发文件名
//2.读文件内容,发给服务器
//3.读到文件末尾 ---复制结束
// close
服务器:
socket
bind
listen
accept
//通信
//1.读出文件名
//2.创建同名文件
//3.读数据写到文件中
tcp协议的特点:
1.面向连接
2.可靠传输
3.字节流
二、粘包问题?
---tcp协议导致,网络的协议栈中导致
粘包 1.字节流特点 导致 发送时 ,多个消息,可能组合一起发送 接收时 ,多个消息,组合成一条交给应用层 2.处理 让消息与消息直接能区分开 --- 边界 a.结束标志 \r\n b.固定长度 100字节 c.设计一种消息结构体 //自定义的消息协议struct msg{//headint type; //-1 0 内容大小//bodychar buf[256]; //}msg_t msg;
三、recv、send函数
ssize_t recv(int sockfd, void *buf, size_t len , int flags);功能:从socket中接收信息 参数:@sockfd --- 要操作的socket@buf --- 存放数据的空间 @len --- buf的大小 @flags --- 指定读取信息的操作标志MSG_DONTWAIT返回值:成功 读取到的字节数 失败 -1 && errno ssize_t read( int fd, void *buf, size_t count );recv(sockfd,buf,sizeof(buf),0);<=>read(sockfd,buf,sizeof(buf),0);ssize_t send(int sockfd, const void *buf, size_t len , int flags);功能:向socket中发送信息 参数:@sockfd --- 要操作的socket@buf --- 存放数据的空间 @len --- 发送的数据大小 @flags --- 操作标志MSG_DONTWAIT返回值:成功 发送出去字节数 失败 -1 && errno ssize_t write( int fd, const void *buf, size_t count);
四、sendto和receivefrom函数
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);ssize_t send(int sockfd, const void *buf, size_t len, int flags);功能:向socket中发送信息 参数:@sockfd --- 要操作的socket@buf --- 存放数据的空间 @len --- 发送的数据大小 @flags --- 操作标志MSG_DONTWAIT@dest_addr --- 要发送到的目的地址 @addrlen --- 地址大小返回值:成功 发送出去字节数 失败 -1 && errno ssize_t recv (int sockfd, void *buf, size_t len, int flags);ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);功能:从socket中接收信息 参数:@sockfd --- 要操作的socket@buf --- 存放数据的空间 @len --- buf的大小 @flags --- 指定读取信息的操作标志MSG_DONTWAIT@src_addr --- 保存 客户端的地址信息 @addrlen --- 值结果参数 注意: 使用时,需要 初始化 addrlen = sizeof(struct sockaddr_in);返回值:成功 读取到的字节数 失败 -1 && errno
五、udp 另外一种网络通信的模型
- udp协议 :无连接 、不可靠 、 数据报
- 决定: 应用场景:效率 实时性
编程:c/s udp客户端:socket //fgets(buf);sendto(clifd,buf)recvfromprintf();udp服务器:socketbind //固定的地址信息 recvfrom(cliaddr);printf();fgets();sendto
六、UDP的聊天室:
server |---client1|---client2|---client3 //v1版本
client1 ------ server
//上线 //服务器收到信息后,转发给其它在线的客户端
//聊天 //服务器收到信息后,转发给其它在线的客户端
//下线 //服务器收到信息后,转发给其它在线的客户端//v2版本
client2 ------ server<-type+text-->//上线 //服务器收到信息后,转发给其它在线的客户端//问题: 1.知道其它客户端是否在线?// 1.1 记录和保存客户端的信息 (地址信息 + 状态) // 处理逻辑:// 保存客户端地址信息// 记录对应状态 ? //表//1.数组 //2.链表 //聊天 //服务器收到信息后,检测表中,在线客户端,转发给它 //下线 //服务器收到信息后,检测表中,在线客户端,转发给它//表中的数据, 状态 下线 broadcast_msg //广播 //v3版本 //v3版本 ---代码思路
//经验:
//先写思路(注释),后写代码
client2 ------ server<-type+text-->//上线 //服务器收到信息后,转发给其它在线的客户端//问题: 1.知道其它客户端是否在线?// 1.1 记录和保存客户端的信息 (地址信息 + 状态) // 处理逻辑:// 保存客户端地址信息// 记录对应状态 ? //表//1.数组 //2.链表 客户端
//上线
step0:step1:step2:服务器:
step0:step1:step2://聊天 //服务器收到信息后,检测表中,在线客户端,转发给它 客户端聊天:do_send(?)
{
while (1)
{msg.type = CHAT;fgets(msg.text)sendto();if(quit?){}
}
}
do_recv()
{while (1){msgrecvfrom(msg)msg.namemsg.text }
} 服务器如果是登录信息://记录到表中 //给表中在线的其它客户端转发一份 memcmp strcmp //下线 //服务器收到信息后,检测表中,在线客户端,转发给它//表中的数据, 状态 下线
http
-------------------------------------------------------------
服务器:api.k780.com 同时能处理多个客户端的请求 做出回应 //单客户端
socket
bind
listen
confd = accpet
while(1)
{readsprintfwrite
}//多客户端
socket //listenfd
bind //绑定服务器端的地址
listen //监听客户端的连接请求 --- 请求队列
while(1) //提取多个客户端的连接请求 建立连接
{confd = accpet //请求队列中提取已连接的请求 返回连接好的socket的fd//通信while(1){readsprintfwrite}
}