Liunx - 网络编程
一 基础知识
1. TCP / UDP
- TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。
- TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
- TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
- 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
- TCP首部开销20字节;UDP的首部开销小,只有8个字节。
- TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。
2. 端口
一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等
这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。
实际上是通过“IP地址+端口号”来区 分不同的服务的。端口提供了一种访问通道,服务器一般都是通过知名端口号来识别的。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TFTP(简单文件传送协议)服务器的UDP端口号都是69
3. 字节序
- Little endian(小端字节序):将低序字节存储在起始地址
- Big endian(大端字节序):将高序字节存储在起始地址
二 代码实现
1. 编程思路
1.1 服务器
- 表名身份(服务器)
- 连接方式(TCP / UDP)
- IP 地址
- 端口
- 等待访问
1.2 客户端
- 获取服务器 IP
- 获取服务器端口连接
2. 相关 API
3. socket 服务器端 / 客户端 开发步骤
- 创建套接字
- 套接字添加信息 (IP 地址 和 端口 )
- 监听网络连接
- 监听到有客户端接入,接受连接
- 数据交互
- 关闭套接字,关闭连接
4. 代码实现
服务端
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// 服务端
int main(int argc,char **argv){
int s_fd ;
int c_fd ;
int n_read ;
char sendBuf[128] = "welcome!!!";
char readBuf[128] = {0};
struct sockaddr_in s_addr ;
struct sockaddr_in c_addr ;
memset(&s_addr , 0 , sizeof(struct sockaddr_in));
memset(&c_addr , 0 , sizeof(struct sockaddr_in));
if(argc != 3 ){
perror("argc");
}
// 1. socket
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1 ){
perror("socket");
exit(-1);
}
// 2. bind
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&s_addr.sin_addr);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
// 3. listen
listen(s_fd,10);
while(1){
// 4. accept
int clen = sizeof(struct sockaddr_in);
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd == -1 ){
perror("accept\n");
exit(-1);
}
if(fork() == 0 ){
while(1){
// 6. write
// char* msg = "welcome !!! \n" ;
printf("client ip is %s ",inet_ntoa(c_addr.sin_addr));
printf(">");
gets(sendBuf);
write(c_fd , sendBuf,strlen(sendBuf));
printf("\n");
}
}
if(fork() == 0){
while(1){
// 5. read
memset(readBuf,0,sizeof(readBuf));
n_read = read(c_fd,readBuf,128);
if(n_read == -1 ){
perror("read");
exit(-1);
}else{
printf("mess is %s\n",readBuf);
}
}
}
}
return 1 ;
}
客户端
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc , char **argv){
int c_fd;
int n_read;
char readBuf[128];
//char* msg = "hello this is laopi server \n" ;
char sendBuf[128] = {0};
struct sockaddr_in c_addr ;
memset(&c_addr , 0 , sizeof(struct sockaddr_in));
if(argc != 3){
perror("argc");
}
// 1. socket
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd == -1 ){
perror("socket\n");
exit(-1);
}
c_addr.sin_family = AF_INET ;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
// 2. connect
if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1)
{
perror("connect\n");
exit(-1);
}
if(fork() == 0 ){
while(1){
// 5. read
memset(readBuf,0,128);
n_read = read(c_fd,readBuf,128);
if(n_read == -1 ){
perror("read");
exit(-1);
}else{
printf("server %s port %s : %s \n",argv[1],argv[2],readBuf);
}
}
}
while(1){
memset(sendBuf,0,sizeof(sendBuf));
printf(">");
gets(sendBuf);
// 3.send
write(c_fd ,sendBuf,strlen(sendBuf));
printf("\n");
}
return 1 ;
}