赞
踩
Server.c
socket
bind (服务器的ip+端口)
listen
accept
recv / send
close
Client.c
socket
connect (服务器的ip+端口)
send / recv
close
扩展:
(1) 三路握手: TCP建立连接时
1)SYN请求 (客户端-->服务器)
2)SYN+ACK应答 (服务器-->客户端)
3)ACK确认 (客户端-->服务器)
(2) 四次挥手: TCP断开连接时
1)FIN请求 (客户端-->服务器)
2)ACK应答 (服务器-->客户端)
3)FIN请求 (服务器-->客户端)
4)ACK应答 (客户端-->服务器)
Server.c
socket
bind (服务器的ip+端口)
recvfrom / sendto
close
Client.c
socket
//设置服务器的ip和端口
sendto / recvfrom
close
-
- 利用UDP 实现简单的通信 UDP ---> SOCK_DGRAM 数据报套接字类型
- udp_server.c 接收数据
-
- int main( int argc, char *argv[] )
- {
- //1.创建套接字 UDP ---> SOCK_DGRAM 数据报套接字
- int server_fd = socket( AF_INET, SOCK_DGRAM, 0 );
- if( server_fd == -1 )
- {
- perror("socket server error ");
- return -1;
- }
- printf("server_fd = %d\n", server_fd );
-
- //2.绑定服务器的ip和端口
- struct sockaddr_in server_addr;
- server_addr.sin_family = AF_INET; //协议族
- server_addr.sin_port = htons( atoi(argv[2]) ); //端口号
- inet_aton( argv[1], &server_addr.sin_addr ); //IP地址
-
- int re = bind( server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );
- if( re == -1 )
- {
- perror("bind server error ");
- return -1;
- }
- printf("bind server success\n");
-
- //3.通信
- while( 1 )
- {
- //接收数据
- char buf[128] = {0};
- struct sockaddr_in client_addr;
- socklen_t len = sizeof(client_addr);
-
- re = recvfrom( server_fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len );
- if( re >= 0 )
- {
- printf("%s : %s\n", inet_ntoa(client_addr.sin_addr), buf );
- }
- else
- {
- perror("recvfrom server error ");
- break;
- }
-
- //人为定义退出条件
- if( buf[0] == '#' )
- {
- break;
- }
- }
-
- //4.关闭套接字
- close( server_fd );
- }
-
- udp_client.c 发送数据
-
- int main( int argc, char *argv[] )
- {
- //1.创建套接字 UDP ---> SOCK_DGRAM 数据报套接字
- int client_fd = socket( AF_INET, SOCK_DGRAM, 0 );
- if( client_fd == -1 )
- {
- perror("socket client error ");
- return -1;
- }
- printf("client_fd = %d\n", client_fd );
-
- //2.设置服务器的ip和端口
- struct sockaddr_in server_addr;
- server_addr.sin_family = AF_INET; //协议族
- server_addr.sin_port = htons( atoi(argv[2]) ); //端口号
- inet_aton( argv[1], &server_addr.sin_addr ); //IP地址
-
- //3.通信
- while(1)
- {
- //发送数据
- char buf[128] = {0};
- printf("input data : ");
- fgets(buf, sizeof(buf), stdin);
-
- int re = sendto( client_fd, buf, strlen(buf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr) );
- if( re == -1 )
- {
- perror("sendto error ");
- break;
- }
-
- //人为定义退出条件
- if( buf[0] == '#' )
- {
- break;
- }
- }
-
- //4.关闭套接字
- close( client_fd );
- }
UNIX域协议是利用socket编程接口 来实现 本地进程之间(客户端/服务器)的通信,它是进程间通信(IPC)的一种方式。它使用文件系统中的路径名来标识服务器和客户端。
UNIX域协议的套接字:
SOCK_STREAM ---> TCP 面向字节流
SOCK_DGRAM ---> UDP 面向数据报
其编程接口 和 流程 与 ipv4协议族是一样的
只不过 协议族为 AF_UNIX , 对应的地址结构体为
UNIX域协议地址结构体 ( man 7 unix )
#include <sys/un.h>
struct sockaddr_un
{
sa_family_t sun_family; /* 协议族 AF_UNIX */
char sun_path[108]; /* UNIX域协议的地址,在本地文件系统中的“绝对路径名” pathname */
};
#define UNIX_PATH "/home/china/unix2418F"
实现方法: UDP / TCP
- 练习:
- 利用UNIX域协议 实现简单的通信 (以UDP为例)
-
- unix_server.c 接收数据
-
- int main( int argc, char *argv[] )
- {
- //删除
- unlink( UNIX_PATH );
-
- //1.创建套接字 AF_UNIX
- int server_fd = socket( AF_UNIX, SOCK_DGRAM, 0 );
- if( server_fd == -1 )
- {
- perror("socket server error ");
- return -1;
- }
-
- //2.绑定 服务器的地址
- struct sockaddr_un server_addr;
- server_addr.sun_family = AF_UNIX; //协议族
- strcpy( server_addr.sun_path, UNIX_PATH ); //unix域协议的地址
-
- int re = bind( server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );
- if( re == -1 )
- {
- perror("bind server error ");
- close( server_fd );
- return -1;
- }
- printf("bind server success\n");
-
- struct sockaddr_un client_addr;
- socklen_t len = sizeof(client_addr);
-
- //3.通信
- while(1)
- {
- //接收数据
- char buf[128] = {0};
- re = recvfrom( server_fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len );
- if( re >= 0 )
- {
- printf("recv : %s\n", buf );
- }
- else
- {
- perror("recvfrom server error ");
- break;
- }
-
- if( buf[0] == '#' )
- {
- break;
- }
- }
-
- //4.关闭套接字
- close( server_fd );
- }
-
-
- unix_client.c 发送数据
-
- //1.创建套接字
- //2.设置服务器的地址
- //3.通信
- //4.关闭套接字
套接字选项是用来设置或获取套接字的一些特性的选项。
每个套接字在不同的层次上(级别) 有不同的行为属性(选项)
有两个接口函数用来 获取和设置 套接字的选项:
getsockopt
setsockopt
NAME
getsockopt, setsockopt - get and set options on sockets
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
功能:获取/设置套接字的选项
参数:
sockfd:指定要操作的套接字描述符
level:级别,不同的选择在不同的级别上(查看资料)
optname:选项名
optval: 通用指针
get 用来保存获取到的选项值
set 用来保存要设置的选项值
不同的选项 对应的类型是不一样的
如果为 int ---> 0 禁用选项
--> 非0 使能选项
optlen:
get 指针,指向空间保存选项值的空间的长度
set 变量,用来指定要设置的选项值的长度
返回值:
成功,返回0
失败,返回-1,同时errno被设置
-
- 设置 端口号重用
-
- 选项名: SO_REUSEPORT
- 级别: SOL_SOCKET
- 值的类型: int
-
- /设置端口号重用
- int n = 1;
- setsockopt( server_sock, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n) );
www.baidu.com ----> 域名
DNS:是把一个域名 转换成 相应的ip地址的服务
DNS协议 传输层用到UDP协议
DNS Server
ip: 114.114.114.114
端口 53
基于UDP的传输层协议
服务器:
阿里云 : 182.92.12.11
端口: 123
- 利用TCP 写一个网络传输文件的程序
- file_tcp_server.c 服务器 接收文件
- file_tcp_client.c 客户端 发送文件
-
- 注意:
- 通信双方 发送和接收的 数据、大小、顺序 要保持一致
- 遵守通信双向的约定 ---> "协议"
-
- file_tcp_server.c 服务器 接收文件
-
- int recv_file( int sock_fd )
- {
- //切换路径
- chdir("../");
-
- //接收文件名的长度大小
- int name_len = 0;
- int re = recv( sock_fd, &name_len, sizeof(name_len), 0 );
- if( re == -1 )
- {
- perror("recv name_len error ");
- return -1;
- }
- printf("recv name_len success , len = %d\n", name_len );
-
- //接收文件名
- char filename[128] = {0};
- re = recv( sock_fd, filename, name_len, 0 );
- if( re == -1 )
- {
- perror("recv filename error ");
- return -1;
- }
- printf("recv filename success , filename = %s\n", filename );
-
-
- //接收文件的大小
- int file_size = 0;
- re = recv( sock_fd, &file_size, sizeof(file_size), 0 );
- if( re == -1 )
- {
- perror("recv file_size error ");
- return -1;
- }
- printf("recv file_size success , file_size = %d\n", file_size );
-
- /* 接收文件的内容
- 创建并打开文件
- 接收数据
- 写入文件
- 关闭文件
- */
- //创建并打开文件
- int fd = open( filename, O_RDWR | O_CREAT | O_EXCL, 0666 );
- if( fd == -1 )
- {
- if( errno == EEXIST ) //文件已经存在,就直接打开即可
- {
- fd = open( filename, O_RDWR | O_TRUNC );
- }
- else
- {
- perror("open file error ");
- return -1;
- }
- }
-
- int write_size = 0; //已经写入的字节数
- while( write_size < file_size )
- {
- //先接收数据
- char buf[128] = {0};
- re = recv( sock_fd, buf, 100, 0 );
- if( re > 0 )
- {
- //写入文件
- write( fd, buf, re );
- write_size += re;
- }
- else
- {
- perror("recv file error ");
- break;
- }
- }
-
- if( write_size == file_size )
- {
- printf("recv file success\n");
- }
- else
- {
- printf("recv file failed \n");
- }
-
- //关闭文件
- close( fd );
- }
-
- int main( int argc, char *argv[] )
- {
- //1.创建套接字
- int server_fd = socket( AF_INET, SOCK_STREAM, 0 );
- if( server_fd == -1 )
- {
- perror("socket server error ");
- return -1;
- }
- printf("server_fd = %d\n", server_fd );
-
- //2.绑定 服务器的ip和端口
- struct sockaddr_in server_addr;
- server_addr.sin_family = AF_INET; //协议族
- server_addr.sin_port = htons( atoi(argv[2]) ); //端口号
- inet_aton( argv[1], &server_addr.sin_addr ); //IP地址
-
- //设置端口号重用
- int n = 1;
- setsockopt( server_fd, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n) );
-
- int re = bind( server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );
- if( re == -1 )
- {
- perror("bind server error ");
- close( server_fd );
- return -1;
- }
- printf("bind server success\n");
-
- //3.监听
- re = listen( server_fd, 5 );
- if( re == -1 )
- {
- perror("listen server error ");
- close( server_fd );
- return -1;
- }
- printf("listen server success\n");
-
- //4.接受连接
- struct sockaddr_in client_addr;
- socklen_t len = sizeof(client_addr);
-
- int client_fd = accept( server_fd, (struct sockaddr *)&client_addr, &len );
- if( client_fd == -1 )
- {
- perror("accept error ");
- close( server_fd );
- return -1;
- }
- printf("client_fd = %d\n", client_fd );
- printf("client_ip = %s\n", inet_ntoa(client_addr.sin_addr) );
-
-
- //5.通信 -->接收文件
- recv_file( client_fd );
-
-
- //6.关闭套接字
- close( server_fd );
- }
-
- file_tcp_client.c 客户端 发送文件
-
- int send_file( int sock_fd, char * filename )
- {
- //发送文件名的长度大小
- int name_len = strlen(filename);
- int re = send( sock_fd, &name_len, sizeof(name_len), 0 );
- if( re == -1 )
- {
- perror("send name_len error ");
- return -1;
- }
- printf("send name_len success , len = %d\n", name_len );
-
- //发送文件名
- re = send( sock_fd, filename, name_len, 0 );
- if( re == -1 )
- {
- perror("send filename error ");
- return -1;
- }
- printf("send filename success , filename = %s\n", filename );
-
- //发送文件的大小
- struct stat st;
- stat( filename, &st ); //获取文件属性-->文件大小
- int file_size = st.st_size;
-
- re = send( sock_fd, &file_size, sizeof(file_size), 0 );
- if( re == -1 )
- {
- perror("send file_size error ");
- return -1;
- }
- printf("send file_size success , file_size = %d\n", file_size );
-
- /* 发送文件的内容
- 打开文件
- 读取
- 发送
- 关闭文件
- */
- //打开文件
- int fd = open( filename, O_RDONLY );
- if( fd == -1 )
- {
- perror("open file error ");
- return -1;
- }
-
- int read_size = 0; //已经读取到的字节数
- while( read_size < file_size )
- {
- //先读取文件内容
- char buf[128] = {0};
- re = read( fd, buf, 100 );
- if( re > 0 )
- {
- //发送数据
- send( sock_fd, buf, re, 0 );
- read_size += re;
- }
- else
- {
- perror("read file error ");
- break;
- }
- }
-
- if( read_size == file_size )
- {
- printf("send file success\n");
- }
- else
- {
- printf("send file failed \n");
- }
-
- //关闭文件
- close( fd );
-
- }
-
-
- int main( int argc, char *argv[] )
- {
- //1.创建套接字
- int client_fd = socket( AF_INET, SOCK_STREAM, 0 );
- if( client_fd == -1 )
- {
- perror("socket client error ");
- return -1;
- }
- printf("client_fd = %d\n", client_fd );
-
- //2.设置服务器的ip和端口
- struct sockaddr_in server_addr;
- server_addr.sin_family = AF_INET; //协议族
- server_addr.sin_port = htons( atoi(argv[2]) ); //端口号
- inet_aton( argv[1], &server_addr.sin_addr ); //IP地址
-
- //3.连接服务器
- int re = connect( client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );
- if( re == -1 )
- {
- perror("connect error ");
- close( client_fd );
- return -1;
- }
- printf("connect success\n");
-
-
- //4.通信 --> 发送文件
- send_file( client_fd, argv[3] );
-
-
- //5.关闭套接字
- close( client_fd );
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。