【linux草鞋应用编程系列】_5_ Linux网络编程
一、网络通信简介
NAME
socket - create an endpoint for communication //功能: 用来创建一个终端的链接 SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h> int socket(int domain, //这个参数用来选择网络协议族,
int type, //用来指定套接类型,
int protocol); //这个参数一般指定为0 除非用于创建原始协议族时才设置为其他值
#include <sys/socket.h> int socketfd ; socketfd=socket(PF_INET,SOCK_STREAM,);
if(- == socketfd)
{
perror("service");
return socketfd;
}
NAME
bind - bind a name to a socket //为套接字指定名称
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
int bind( int sockfd, //套接字文件描述符
const struct sockaddr *my_addr, //通用的套接字地址指针
socklen_t addrlen); //第二个参数占用的字节数 sizeof(my_addr)
DESCRIPTION
bind() gives the socket sockfd the local address my_addr. my_addr is
addrlen bytes long. Traditionally, this is called “assigning a name to
a socket.” When a socket is created with socket(), it exists in a
name space (address family) but has no name assigned.
/*
* 1003.1g requires sa_family_t and that sa_data is char.
*/
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[]; /* 14 bytes of protocol address */
};
struct sockaddr_in {
sa_family_t sin_family; /* Address family */ //socket 网络协议族类型
__be16 sin_port; /* Port number */ //要绑定的本地端口号
struct in_addr sin_addr; /* Internet address*/ //本机的IP地址 /* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)]; // 第四个域通常不用赋值
};
struct in_addr 的定义如下:
/* Internet address. */
struct in_addr {
__be32 s_addr;
};
NAME
inet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr,
inet_lnaof, inet_netof - Internet address manipulation routines SYNOPSIS
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp); //将字符串"192.168.0.12"转换为32bit的IP地址
in_addr_t inet_network(const char *cp);
char *inet_ntoa(struct in_addr in); //将32bit的IP地址转换为 "192.168.0.12"字符串
struct in_addr inet_makeaddr(int net, int host);
in_addr_t inet_lnaof(struct in_addr in);
in_addr_t inet_netof(struct in_addr in);
#include <sys/socket.h>
#include <netinet/in.h> struct sockaddr_in bind_addr;
socklen_t addr_len; //绑定本地端口,即为socketfd命名
bind_addr.sin_family = AF_INET;
bind_addr.sin_port= htons (); //通讯端口,服务器端和客户机端必须一样
bind_addr.sin_addr.s_addr= inet_addr("192.168.0.101"); //本机的IP地址
addr_len=sizeof(struct sockaddr_in);
ret = bind(socketfd,(struct sockaddr*)&bindaddr, addr_len);
if(-==ret)
{
perror("bind");
return ret;
}
LISTEN() Linux Programmer’s Manual LISTEN()
NAME
listen - listen for connections on a socket
SYNOPSIS
#include <sys/socket.h> int listen(int sockfd, //要监听的网络套接字文件描述符
int backlog); //可以服务的最大客户端数目,或者说监听队列的长度
#include <sys/socket.h> socketfd = listen(socketfd, );
ACCEPT() Linux Programmer’s Manual ACCEPT()
NAME
accept - accept a connection on a socket
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h> int accept( int sockfd, //要监听的网络套接字文件的描述符
struct sockaddr *addr, //输出参数,用来存放接收到的客户机的网络地址信息
socklen_t *addrlen); //输出参数,用来存放客户机的网络地址信息的长度
#include <sys/socket.h> struct sockaddr_in client_addr;
socklen_t client_addr_len; //响应监听队列的请求,并创建缓存数据文件
client_addr_len = sizeof(struct sockaddr_in);
sockbuf_fd=accept(socketfd,(struct sockaddr*)&client_addr, &client_addr_len);
if(- == sockbuf_fd)
{
perror("accept");
return sockbuf_fd;
}
Exp:
//发送数据
ret=write(sock_buf_fd,"socket network serives test.\n",);
if(- == ret)
{
perror("send data");
return ret;
} //接收数据
memset(sock_buf,,sizeof(sockbuf));
ret=read(sock_buf_fd,sock_buf,sizeof(sock_buf));
if(- == ret)
{
perror("read socket");
return ret;
}
close(sock_buf_fd);
close(socket_fd);
int socket_fd; socket_fd = socket( PF_INET,
SOCK_STREAM,
);
CONNECT() Linux Programmer’s Manual CONNECT()
NAME
connect - initiate a connection on a socket
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h> int connect( int sockfd, //建立的套接字文件
const struct sockaddr *serv_addr, //指定要连接到服务的地址信息结构体的指针
socklen_t addrlen); //参数2 的长度
#include <sys/socket.h>
#include <netinet/in.h> int ret;
struct sockaddr_in srv_addr; srv_addr.sin_family =AF_INET;
srv_addr.sin_port= htons();
srv_addr.sin_addr.s_addr= inet_addr("192.168.0.101");
ret =connect(socket_fd , (struct sockaddr*)&srv_addr , sizeof(struct sockaddr_in) )
memset(buf, , sizeof(buf) ); //将缓冲区域清空的原因是定义的buf里面存在一些其他数据,如果不清空,数据将错误
ret=read(socket_fd,buf,sizeof(buf));
if(ret<)
{
perror("read");
return ret;
} ret=write(socket_fd,buf,strlen(buf)); //如果在读之前不清空 buf ,那么这个地方 strlen(buf) 就要改为 ret ;
if(ret<)
{
perror("write");
return ret;
}
socket network serives test.
�@V@�R@PP@�R@qr@. //打印出现乱码。
//本文件用来测试网络通信
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h> int main(int argc,char* argv[])
{
int socket_fd;
int ret;
struct sockaddr_in bind_addr;
struct sockaddr_in client_addr;
socklen_t addr_len;
int sock_buf_fd;
char sock_buf[]; //创建网络套接字
socket_fd=socket(PF_INET,SOCK_STREAM,);
if(- == socket_fd)
{
perror("service");
return socket_fd;
} //绑定本地端口,即为socket_fd命名
bind_addr.sin_family = PF_INET;
bind_addr.sin_port= htons ();
bind_addr.sin_addr.s_addr= inet_addr("192.168.0.101");
addr_len=sizeof(struct sockaddr_in);
ret = bind(socket_fd,(struct sockaddr*)&bind_addr, addr_len); //监听端口
ret=listen(socket_fd, );
if(- == ret)
{
perror("listen");
return ret;
} //响应监听队列的请求,并创建缓存数据文件
sock_buf_fd=accept(socket_fd,(struct sockaddr*)&client_addr,&addr_len);
if(- == sock_buf_fd)
{
perror("accept");
return sock_buf_fd;
} //发送数据
ret=write(sock_buf_fd,"socket network serives test.\n",);
if(- == ret)
{
perror("send data");
return ret;
} //接收数据
memset(sock_buf,,sizeof(sock_buf));
ret=read(sock_buf_fd,sock_buf,sizeof(sock_buf));
if(- == ret)
{
perror("read socket");
return ret;
}
printf("%s\n",sock_buf); close(sock_buf_fd);
close(socket_fd);
return ;
}
client.c 当作客户程序
//本文件用来测试linux网络编程 #include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h> int main(int argc,char*argv[])
{
int ret;
int socket_fd;
struct sockaddr_in srv_addr;
socklen_t addr_len;
char buf[]; //创建网络套接字文件
socket_fd=socket(PF_INET,SOCK_STREAM,);
if(- == socket_fd )
{
perror("socket");
return socket_fd;
} //申请建立与服务器的连接
srv_addr.sin_family=PF_INET;
srv_addr.sin_port=htons();
srv_addr.sin_addr.s_addr = inet_addr("192.168.0.101"); //服务器IP地址
addr_len=sizeof(struct sockaddr_in);
ret=connect(socket_fd,(struct sockaddr *)&srv_addr, addr_len);
if(-==ret)
{
perror("connect");
return -;
} memset(buf,,sizeof(buf));
ret=read(socket_fd,buf,sizeof(buf));
if(ret<)
{
perror("read");
return ret;
} ret=write(socket_fd,buf,strlen(buf));
if(ret<)
{
perror("write");
return ret;
} close(socket_fd);
return ;
}
[root@localhost tcpip]# ./service //在服务器端运行 service 程序,执行后再等待客户程序请求服务
socket network serives test. //在客户端执行 ./client 后 打印出这个信息 [root@localhost tcpip]#
/ # ./client
/ #
//本文件是用于简单文件传输程序的头文件
#if !defined(__FTP_H__)
#define __FTP_H__ #define TEL_LEN 512 //报文数据长度为512字节 #define FILE_EXIST 0x0
#define FILE_NOT_EXIST 0x1
#define END_OF_FILE 0x2
#define VALID_DATA 0x3 typedef struct tel_gram
{
unsigned char type;
char data[TEL_LEN]; }tel_t; typedef struct pthread_type
{
struct sockaddr_in *sock_in_addr;
int sock_buf_fd ; }pthread_type_t; #endif
//本文件用来实现一个简单的文件传输服务
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include "ftp.h"
#include <fcntl.h> int transfer(pthread_type_t *arg)
{
int fd;
int ret;
int size;
int sock_buf_fd;
char file_name[];
tel_t telgram;
struct sockaddr_in* cli_addr; //输出客户机信息
cli_addr=arg->sock_in_addr;
printf("the connet client is %s .\n",inet_ntoa(cli_addr->sin_addr.s_addr) );
#if 0
//首先检测链接是否正常
sock_buf_fd=arg->sock_buf_fd;
ret=recv( sock_buf_fd, //接收数据的socket数据缓冲文件
&telgram, //存粗接收数据的缓冲去地址
sizeof(tlegram.type), //要接收的数据长度
); //接收标志
if(ret != sizeof(tlegram.type))
{
printf("network establelish is not well. will exit\n");
return ;
}
send(sock_buf_fd,&telgram,sizeof(tlegram.type),);
#endif //接受文件名
sock_buf_fd=arg->sock_buf_fd;
ret=recv(sock_buf_fd, file_name,,);
if(-==ret)
{
perror("recv file name");
return ;
}
//切换到默认路径,默认文件存放路径为/ftp目录
chdir("/ftp");
if( access(file_name, F_OK) )
{
telgram.type=FILE_NOT_EXIST;
//如果文件不存在就发送信息给客户端
send(sock_buf_fd,&telgram,sizeof(telgram.type),);
return ;
} //打开要传送的文件
fd=open(file_name,O_RDONLY);
if(-==fd)
{
return -;
} while()
{
telgram.type=VALID_DATA;
ret=read(fd, &telgram.data,TEL_LEN);
size=sizeof(telgram);
if(ret<TEL_LEN)
{
telgram.type=END_OF_FILE;
size =ret + sizeof(telgram.type);
}
send(sock_buf_fd,&telgram, size,);
} return ;
} int main(int argc,char* argv[])
{
int sock_fd;
int sock_buf_fd;
int ret;
struct sockaddr_in srv_addr; //服务器IP地址、端口信息
struct sockaddr_in cli_addr; //用来存储客户段地址信息
socklen_t srv_addr_len; //保存服务器IP地址、端口信息的结构体数据长度
socklen_t cli_addr_len; //保存客户机IP地址、端口信息的结构体数据长度 pthread_type_t pth_arg; //建立网络套接字文件
sock_fd=socket(PF_INET, //使用TCP/IP协议族
SOCK_STREAM, //使用字符流,TCP协议,需要建立稳定链接
); //非建立原始协议,必须传 0
if(- == sock_fd )
{
perror("create socket");
return sock_fd;
} //绑定本地端口,即为套接字接口命名
srv_addr.sin_family=PF_INET; //指定绑定的协议
srv_addr.sin_port=htons(); //指定通信端口
srv_addr.sin_addr.s_addr=inet_addr("192.168.0.101"); //指定服务起的IP
srv_addr_len=sizeof(struct sockaddr_in);
ret=bind( sock_fd, //要绑定的套接字文件
(struct sockaddr *)&srv_addr, //服务器网络信息结构体
srv_addr_len); //第二个参数的sizeof
if(- == ret)
{
perror("socket bind");
return ret;
} //监听端口
ret=listen(sock_fd, //要监听的套解字,即要监听的端口
); //最大监听队列 if(- == ret)
{
perror("socket liseten");
return ret;
} //查看请求,并建立数据缓存文件
while()
{
sock_buf_fd=accept( sock_fd, //输入参数
(struct sockaddr*)&cli_addr, //输出参数 客户机IP
&cli_addr_len); //第二个参数的sizeof pth_arg.sock_buf_fd=sock_buf_fd; //数据缓存文件指针传递给线程
pth_arg.sock_in_addr=&cli_addr;
ret=transfer(&pth_arg);
if(ret)
{
break ;
}
} close(sock_buf_fd);
close(sock_fd);
return ;
}
//本文件实现简单文件传输软件的客户端
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include "ftp.h" int main(int argc,char* argv[])
{
int fd;
int ret;
int sock_fd;
struct sockaddr_in srv_addr;
tel_t telgram;
int size; //检测程序执行时的参数是否正确
//不正确输出提示信息
if(argc< || argc > )
{
printf("Usage: client filename\n");
return ;
} //打开网络套接字文件
sock_fd=socket( PF_INET, //与服器程序一样
SOCK_STREAM,
);
if(- == sock_fd)
{
perror("socket");
return ;
} //申请与服务器建立连接
srv_addr.sin_family=PF_INET;
srv_addr.sin_port=htons();
srv_addr.sin_addr.s_addr=inet_addr("192.168.0.101");
ret=connect(sock_fd,(struct sockaddr*)&srv_addr, sizeof(srv_addr));
if(- == ret)
{
perror("connet to server");
return ;
} //发送文件名给服务器
send(sock_fd,argv[],strlen(argv[]),);
recv(sock_fd,&telgram,sizeof(telgram.type),);
if(FILE_NOT_EXIST == telgram.type)
{
printf("Not such a file in servie mathcine,will quit transfer\n");
return ;
} //创建文件来接受数据
fd=open(argv[], O_WRONLY | O_CREAT | O_TRUNC);
if(- == fd )
{
perror("create file");
return ;
} while()
{
size=recv(sock_fd, &telgram, sizeof(telgram), );
if(END_OF_FILE == telgram.type)
{
ret=write(fd,&telgram.data,size);
if(ret<size)
{
//如果写入的数据比读到的数据少,表示写入错误删除文件
unlink(argv[]);
perror("local file write");
}
break;
} ret=write(fd, &telgram.data, size);
if(ret<size)
{
//如果写入的数据比读到的数据少,表示写入错误删除文件
unlink(argv[]);
perror("local file write");
break ;
}
} close(fd);
close(sock_fd);
return ;
}
【linux草鞋应用编程系列】_5_网络编程
本系列文章欢迎批评指正,欢迎指正错误。
本系列文章,未完待续.........
【linux草鞋应用编程系列】_5_ Linux网络编程的更多相关文章
- linux下的C语言开发(网络编程)
http://blog.csdn.net/feixiaoxing/article/details/7259675 [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing ...
- Java网络编程 -- BIO 阻塞式网络编程
阻塞IO的含义 阻塞(blocking)IO :阻塞是指结果返回之前,线程会被挂起,函数只有在得到结果之后(或超时)才会返回 非阻塞(non-blocking)IO :非阻塞和阻塞的概念相对应,指在不 ...
- Linux非阻塞IO(二)网络编程中非阻塞IO与IO复用模型结合
上文描述了最简易的非阻塞IO,采用的是轮询的方式,这节我们使用IO复用模型. 阻塞IO 过去我们使用IO复用与阻塞IO结合的时候,IO复用模型起到的作用是并发监听多个fd. 以简单的回射服务器 ...
- java 面向对象编程 第18章——网络编程
1. TCP/IP协议模型 应用层:应用程序: 传输层:将数据套接端口,提供端到端的通信服务: 网络互联层:负责数据包装.寻址和路由,同时还包含网间控制报文协议: 网络接口层:提供TCP/IP协议的 ...
- Node.js高级编程读书笔记 - 3 网络编程
Outline 3.4 构建TCP服务器 3.5 构建HTTP服务器 3.6 构建TCP客户端 3.7 创建HTTP请求 3.8 使用UDP 3.9 用TLS/SSL保证服务器的安全性 3.10 用H ...
- Linux网络编程经典书籍推荐
UNIX环境高级编程<高级unix环境编程><unix网络编程><深入理解计算机系统>比较好 =====================Linux网络编程经典书籍推 ...
- Linux C高级编程——网络编程基础(1)
Linux高级编程--BSD socket的网络编程 宗旨:技术的学习是有限的,分享的精神是无限的. 一网络通信基础 TCP/IP协议簇基础:之所以称TCP/IP是一个协议簇,是由于TCP/IP包括T ...
- linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解
最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展, ...
- Linux上天之路系列目录
Linux上天之路系列目录 Linux上天之路(一)之Linux前世今生 Linux上天之路(二)之Linux安装 Linux上天之路(三)之Linux系统目录 Linux上天之路(四)之Linux界 ...
- TCP和UDP通信(C#网络编程) ---- 系列文章
文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编程系列文章(二)之Socket实现同步TCP服务器 C#网络编程系列文章(三)之TcpListener实现异步TC ...
随机推荐
- JavaScript算法(归并排序与快速排序)
归并排序与快速排序这两个算法放在一起,也是因为时间复杂度都是对数级别的. 目前看过的资料,归并排序看<学习JavaScript数据结构与算法>介绍的归并排序吧,快速排序直接看百度百科,讲的 ...
- iOS创建安全的单例
创建安全的单例 #import "Singleton.h" @implementation Singleton static Singleton* _instance = nil; ...
- web应用中使用JavaMail发送邮件
现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件.邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息.今天我们也来实现一个这样的功能 ...
- 前端构建工具gulpjs的使用介绍及技巧
gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...
- easyui datagrid cell title换行
" " title="' +row.TaskName + "
- mysql导入导出sql文件
window下 1.导出整个数据库mysqldump -u 用户名 -p 数据库名 > 导出的文件名mysqldump -u dbuser -p dbname > dbname.sql2. ...
- SQL 截取字符串
以下代码演示的是除去字符串后四位 ,) 下面是SUBSTRING的解释 SUBSTRING ( expression ,start , length ) 第一个参数是字符串,第二个是起始位置,第三个是 ...
- 一张图理解prototype、proto和constructor的三角关系
× 目录 [1]图示 [2]概念 [3]说明[4]总结 前面的话 javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则 ...
- Huffman树进行编码和译码
//编码#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> ...
- 【原创】开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...