linux网络编程(一)
一.概念介绍
网络程序分为服务端程序和客户端程序。服务端即提供服务的一方,客户端为请求服务的一方。但实际情况是有些程序的客户端、服务器端角色不是这么明显,即互为客户端和服务端。
我们编写网络程序时,一般是基于TCP协议或者UDP协议进行网络通信的。
TCP:(Transfer Control Protocol)传输控制协议是一种面向连接的协议, 当我们的网络程序使用这个协议的时候,网络可以保证我们的客户端和服务端之间的传输是可靠的。
UDP:(User Datagram Protocol)用户数据报协议是一种非面向连接的协议, 这种协议并不能保证我们的网络程序的连接是可靠的。
我们编写的网络程序具体采用哪一类协议,要视具体情况而定。比如,如果是大数据量的通信,而且对数据的完整性要求不是特别高,则可以采用UDP协议,以得到更快的传输速率。如果我们是要实现一些诸如文件传输、社交通讯之类的功能,就需要采用TCP协议通信,以保证传输的可靠性。
二.初等网络函数介绍
int socket(int domain, int type,int protocol)
domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等).
AF_UNIX只能够用于单一的Unix 系统进程间通信,
而AF_INET是针对Internet的,因而可以允许在远程
主机之间通信(当我们 man socket时发现 domain可选项是 PF_*而不是AF_*,因为glibc是posix的实现所以用PF代替了AF,
不过我们都可以使用的).
type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)
SOCK_STREAM表明我们用的是TCP 协议,这样会提供按顺序的,可靠,双向,面向连接的比特流.
SOCK_DGRAM 表明我们用的是UDP协议,这样只会提供定长的,不可靠,无连接的通信.
protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了 socket为网络通讯做基本的准备.
成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况.
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
sockfd:是由socket调用返回的文件描述符.
addrlen:是sockaddr结构的长度.
my_addr:是一个指向sockaddr的指针. 在中有 sockaddr的定义
struct sockaddr{
unisgned short as_family;
char sa_data[14];
};
不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sockaddr_in) 来代替.在中有sockaddr_in的定义
struct sockaddr_in{
unsigned short sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
}
我们主要使用Internet所以
sin_family一般为AF_INET,
sin_addr设置为INADDR_ANY表示可以和任何的主机通信,
sin_port是我们要监听的端口号.sin_zero[8]是用来填充的.
bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样
int listen(int sockfd,int backlog)
sockfd:是bind后的文件描述符.
backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示可以介绍的排队长度.
listen函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.
int accept(int sockfd, struct sockaddr *addr,int *addrlen)
sockfd:是listen后的文件描述符.
addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen和accept是服务器端用的函数,
accept调用时,服务器端的程序会一直阻塞到有一个 客户程序发出了连接. accept成功时返回最后的服务器端的文件描述符,
这个时候服务器端可以向该描述符写信息了. 失败时返回-1
int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)
sockfd:socket返回的文件描述符.
serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址
addrlen:serv_addr的长度
connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符 失败时返回-1.
更多函数请查看man …….
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
三.初等网络函数使用实例
一个教科书式的服务器端程序流程为:
建立套接字socket()--->将套接字绑定到ip地址bind()----->建立监听套接字listen()------>开始等待客户端请求accpet()
详细代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <netdb.h>
int main(int argc, char *argv[])
{
int sockfd,connfd;
struct sockaddr_in srvaddr;
struct sockaddr_in cliaddr;
int len,port;
char hello[]="Hi,welcome to linux-code!\n";
if((sockfd=socket(AF_INET,SOCK_STREAM,))==-){
fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
exit();
}
/* 服务器端填充 sockaddr结构 */
bzero(&srvaddr,sizeof(struct sockaddr_in));
srvaddr.sin_family=AF_INET;
srvaddr.sin_addr.s_addr=htonl(INADDR_ANY);
srvaddr.sin_port=htons();
/* 捆绑sockfd描述符 */
if(bind(sockfd,(struct sockaddr *)(&srvaddr),sizeof(struct sockaddr))==-){
fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
exit();
}
/* 监听sockfd描述符 */
if(listen(sockfd,)==-){
fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
exit();
}
len=sizeof(struct sockaddr_in);
while(){ /* 服务器阻塞,直到客户程序建立连接 */
if((connfd=accept(sockfd,(struct sockaddr *)(&cliaddr),&len))==-){
fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
exit();
}
fprintf(stderr,"Server get connection from %s\n",inet_ntoa(cliaddr.sin_addr));
if(write(connfd,hello,strlen(hello))==-){
fprintf(stderr,"Write Error:%s\n",strerror(errno));
exit();
}
/* 这个通讯已经结束 */
close(connfd);
/* 循环下一个 */
}
close(sockfd);
exit();
}
一个教科书式的客户端程序流程为:
建立套接字socket()--->与服务器建立连接connect()
详细代码如下:
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <netdb.h> int main(int argc, char *argv[]) { int sockfd; char buf[]; struct sockaddr_in srvaddr; struct hostent *phost; int nbytes; if(argc!=){ fprintf(stderr,"Usage:%s <IP> <portnumber>\a\n",argv[]); exit(); } /* 客户程序开始建立 sockfd描述符 */ if((sockfd=socket(AF_INET,SOCK_STREAM,))==-){ fprintf(stderr,"socket Error:%s\a\n",strerror(errno)); exit(); } /* 客户程序填充服务端的资料 */ bzero(&srvaddr,sizeof(srvaddr)); srvaddr.sin_family=AF_INET; srvaddr.sin_port=htons(atoi(argv[])); if (inet_pton(AF_INET, argv[], &srvaddr.sin_addr) <= ){ fprintf(stderr,"inet_pton Error:%s\a\n",strerror(errno)); exit(); } /* 客户程序发起连接请求 */ if(connect(sockfd,(struct sockaddr *)(&srvaddr),sizeof(struct sockaddr))==-){ fprintf(stderr,"connect Error:%s\a\n",strerror(errno)); exit(); } /* 连接成功了 */ if((nbytes=read(sockfd,buf,))==-){ fprintf(stderr,"read Error:%s\n",strerror(errno)); exit(); } buf[nbytes]='\0'; printf("received data:%s\n",buf); /* 结束通讯 */ close(sockfd); exit(); }
四.上述程序存在的问题
先运行上述程序的服务端程序,再运行客户端程序,可以得到如下结果:
服务器端结果:
viidiot@ubuntu:~/code $ ./srv
Server get connection from 192.168.1.153
Server get connection from 127.0.0.1
Server get connection from 192.168.1.153
客户器端结果:
viidiot@ubuntu:~/code $ ./cli 192.168.1.153 1113
received data:Hi,welcome to linux-code!
我们完成了一个简单的网络通信程序,该程序使用的io模型为同步(synchronous)阻塞(blocking)。服务器端调用accept(),write()等函数,如果没有客户端连接过来或者相应的文件描述符没有准备好写,程序就会在那里死死的等待,什么事情也不干。在实际应用中,这类程序是很少出现的。实际中使用的都是异步io模型。
有空我们再来看看:同步、异步,阻塞、非阻塞,select()/poll()/epoll()
linux网络编程(一)的更多相关文章
- 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"
[深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...
- 【linux草鞋应用编程系列】_5_ Linux网络编程
一.网络通信简介 第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章. 二.linux网络通信 在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...
- Linux 网络编程(IO模型)
针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...
- linux网络编程 no route to host 解决方案
linux网络编程 no route to host 解决方案 [整合资料] (2013-05-13 21:38:12) 转载▼ 标签: net iptables it 分类: Linux 参考资料h ...
- linux网络编程-(socket套接字编程UDP传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
- Linux网络编程&内核学习
c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...
- linux网络编程_1
本文属于转载,稍有改动,以利于学习. (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个 ...
- Linux网络编程入门 (转载)
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- Linux网络编程必看书籍推荐
首先要说讲述计算机网络和TCP/IP的书很多. 先要学习网络知识才谈得上编程 讲述计算机网络的最经典的当属Andrew S.Tanenbaum的<计算机网络>第五版,这本书难易适中. &l ...
- [转] - Linux网络编程 -- 网络知识介绍
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
随机推荐
- rdlc报告vs2008编辑正常,在vs2012在对错误的编辑
最近我们的系统开发的工具vs2008升级到2012,由于系统是非常的报告是由rdlc发展.今天 有需要修改的报告满足需求.直接使用vs2012正确rdlc报告编辑,结果本次变动后.报表都报错. 后来我 ...
- 使用JAVA打开本地应用程序相关的文件
在该项目中需要运行本地文件或应用程序,JDK6添加后Desktop类别.可以直接使用.这使得有可能在程序中无论什么应用程序可以打开的.例:打开pdf文件,当地福昕是默认打开.执行程序将使用福昕开放pd ...
- NET动态调用WebService
NET动态调用WebService 这不是一篇教你了解WebService的博文,也不是对WebService的深入理解, 这是一篇教你在开发过程中,如果动态的调用WebService一个方法. 在比 ...
- 采用RedisLive监控Redis服务
1.基础环境安装https://pypi.python.org/packages/source/b/backports.ssl_match_hostname/backports.ssl_match_h ...
- 1秒破解 js packer 加密
原文:1秒破解 js packer 加密 其实有点标题党了,不过大概就是这个意思. 进入正题, eval(function(p,a,c,k,e,d){e=function(c){return(c< ...
- MyEclipse优化全攻略
(0) 吐槽 Eclipse仅仅是个半成品有木有?什么都须要自己安装插件,新手非常难用有木有? 安装上插件以后了版本号兼容和各种问题烦死人有木有? 都怪碎片和版本号乱公布有木有? IntelliJ I ...
- 深入理解C指针之二:C内存管理
原文:深入理解C指针之二:C内存管理 内存管理对所有程序来说都很重要.有时候内存由运行时系统隐式的管理,比如为变量自动分配内存.在这种情况下,变量分配在它所处的函数的栈帧上(每个函数都有它自己的栈帧, ...
- hdu 4893 Wow! Such Sequence!
http://acm.hdu.edu.cn/showproblem.php?pid=4893 三种操作: 1 k d - "add" 2 l r - "query sum ...
- ExtJs--15--Ext.is*各种类型推断的方法,简单看源代码就能够明确了
/** * Returns true if the passed value is empty, false otherwise. The value is deemed to be empty if ...
- ASP.NET状态服务及session丢失问题解决方案总结
原文:ASP.NET状态服务及session丢失问题解决方案总结[转载] asp.net Session的实现: asp.net的Session是基于HttpModule技术做的,HttpModule ...