socket 网摘
一、基本socket函数
Linux系统是通过提供套接字(socket)来进行网络编程的。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也有一个类似于打
开文件的函数:socket(),调用socket(),该函数返回一个整型的socket的描述符,随后的连接建立、数据传输等操作也都是通过该socket实现。
1、socket函数
syntax:
int socket(int domain, int
type, int protocol);
功能说明:
调用成功,返回socket文件描述符;失败,返回-1,并设置errno
参数说明:
domain指明所使用的协议族,通常为PF_INET,表示TCP/IP协议;
type参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字
protocol通常赋值"0"。
两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。
2、bind函数
syntax:
int bind(int sock_fd,struct
sockaddr_in *my_addr, int addrlen);
功能说明:
将套接字和指定的端口相连。成功返回0,否则,返回-1,并置errno.
参数说明:
sock_fd是调用socket函数返回值,
my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;
struct sockaddr_in结构类型是用来保存socket信息的:
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
addrlen为sockaddr的长度。
3、connect函数
syntax:
int
connect(int sock_fd, struct sockaddr *serv_addr,int addrlen);
功能说明:
客户端发送服务请求。成功返回0,否则返回-1,并置errno。
参数说明:
sock_fd
是socket函数返回的socket描述符;serv_addr是包含远端主机IP地址和端口号的指针;addrlen是结构sockaddr_in的长度。
4、listen函数
syntax:
int listen(int sock_fd, int
backlog);
功能说明:
等待指定的端口的出现客户端连接。调用成功返回0,否则,返回-1,并置errno.
参数说明:
sock_fd 是socket()函数返回值;
backlog指定在请求队列中允许的最大请求数
5、accecpt函数
syntax:
int accept(int sock_fd, struct
sockadd_in* addr, int addrlen);
功能说明:
用于接受客户端的服务请求,成功返回新的套接字描述符,失败返回-1,并置errno。
参数说明:
sock_fd是被监听的socket描述符,
addr通常是一个指向sockaddr_in变量的指针,
addrlen是结构sockaddr_in的长度。
6、write函数
syntax:
ssize_t
write(int fd,const void *buf,size_t nbytes)
功能说明:
write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1.
并设置errno变量.
在网络程序中,当我们向套接字文件描述符写时有俩种可能:
1)write的返回值大于0,表示写了部分或者是全部的数据.
2)返回的值小于0,此时出现了错误.需要根据错误类型来处理.
如果错误为EINTR表示在写的时候出现了中断错误.
如果错误为EPIPE表示网络连接出现了问题.
7、read函数
syntax:
ssize_t
read(int fd,void *buf,size_t nbyte)
函数说明:
read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0
表示已经读到文件的结束了,小于0表示出现了错误.
如果错误为EINTR说明读是由中断引起的,
如果错误是ECONNREST表示网络连接出了问题.
8、close函数
syntax:
int close(sock_fd);
说明:
当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:
函数运行成功返回0,否则返回-1
二、socket编程的其他函数说明
1、 网络字节顺序及其转换函数
1) 网络字节顺序
每一台机器内部对变量的字节存储顺序不同,而网络传输的数据是一定要统一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器,
一定要对数据进行转换,从程序的可移植性要求来讲,就算本机的内部字节表示顺序与网络字节顺序相同也应该在传输数据以前先调用数据转换函数,
以便程序移植到其它机器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。
2) 有关的转换函数
* unsigned short int htons(unsigned short int hostshort):
主机字节顺序转换成网络字节顺序,对无符号短型进行操作4bytes
* unsigned long int htonl(unsigned long int hostlong):
主机字节顺序转换成网络字节顺序,对无符号长型进行操作8bytes
* unsigned short int ntohs(unsigned short int netshort):
网络字节顺序转换成主机字节顺序,对无符号短型进行操作4bytes
* unsigned long int ntohl(unsigned long int netlong):
网络字节顺序转换成主机字节顺序,对无符号长型进行操作8bytes
注:以上函数原型定义在netinet/in.h里
2、IP地址转换
有三个函数将数字点形式表示的字符串IP地址与32位网络字节顺序的二进制形式的IP地址进行转换
(1) unsigned long int inet_addr(const char *
cp):该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型,如:struct sockaddr_in
ina
ina.sin_addr.s_addr=inet_addr("202.206.17.101")
该函数成功时:返回转换结果;失败时返回常量INADDR_NONE,该常量=-1,二进制的无符号整数-1相当于255.255.255.255,这是
一个广播地址,所以在程序中调用iner_addr()时,一定要人为地对调用失败进行处理。由于该函数不能处理广播地址,所以在程序中应该使用函数
inet_aton()。
(2)int inet_aton(const char * cp,struct in_addr *
inp):此函数将字符串形式的IP地址转换成二进制形式的IP地址;成功时返回1,否则返回0,转换后的IP地址存储在参数inp中。
(3) char * inet_ntoa(struct in-addr
in):将32位二进制形式的IP地址转换为数字点形式的IP地址,结果在函数返回值中返回,返回的是一个指向字符串的指针。
3、字节处理函数
Socket地址是多字节数据,不是以空字符结尾的,这和C语言中的字符串是不同的。Linux提供了两组函数来处理多字节数据,一组以b(byte)开头,是和BSD系统兼容的函数,另一组以mem(内存)开头,是ANSI
C提供的函数。
以b开头的函数有:
(1) void bzero(void * s,int
n):将参数s指定的内存的前n个字节设置为0,通常它用来将套接字地址清0。
(2) void bcopy(const void * src,void * dest,int
n):从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域。
(3) int bcmp(const void * s1,const void * s2,int
n):比较参数s1指定的内存区域和参数s2指定的内存区域的前n个字节内容,如果相同则返回0,否则返回非0。
注:以上函数的原型定义在strings.h中。
以mem开头的函数有:
(1) void * memset(void * s,int c,size_t
n):将参数s指定的内存区域的前n个字节设置为参数c的内容。
(2) void * memcpy(void * dest,const void * src,size_t
n):功能同bcopy(),区别:函数bcopy()能处理参数src和参数dest所指定的区域有重叠的情况,memcpy()则不能。
(4) int memcmp(const void * s1,const void * s2,size_t
n):比较参数s1和参数s2指定区域的前n个字节内容,如果相同则返回0,否则返回非0。
注:以上函数的原型定义在string.h中。
二、程序说明
本使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端;客户端在接受到数据后打印出来,然后关闭。
1、client.c
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int cfd;
int recbytes;
int sin_size;
char
buffer[1024]={0};
struct sockaddr_in s_add,c_add;
unsigned short portnum=0x8888;
printf("Hello,welcome to client !\r\n");
cfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == cfd)
{
printf("socket fail ! \r\n");
return
-1;
}
printf("socket ok !\r\n");
bzero(&s_add,sizeof(struct sockaddr_in));
s_add.sin_family=AF_INET;
s_add.sin_addr.s_addr= inet_addr("192.168.1.2");
s_add.sin_port=htons(portnum);
printf("s_addr = %#x ,port :
%#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port);
if(-1 == connect(cfd,(struct sockaddr *)(&s_add),
sizeof(struct sockaddr)))
{
printf("connect fail !\r\n");
return
-1;
}
printf("connect ok !\r\n");
if(-1 == (recbytes = read(cfd,buffer,1024)))
{
printf("read
data fail !\r\n");
return
-1;
}
printf("read ok\r\nREC:\r\n");
buffer[recbytes]='\0';
printf("%s\r\n",buffer);
getchar();
close(cfd);
return 0;
}
2、server.c
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int sfp,nfp;
struct sockaddr_in s_add,c_add;
int sin_size;
unsigned short portnum=0x8888;
printf("Hello,welcome to my server !\r\n");
sfp = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sfp)
{
printf("socket fail ! \r\n");
return
-1;
}
printf("socket ok !\r\n");
bzero(&s_add,sizeof(struct sockaddr_in));
s_add.sin_family=AF_INET;
s_add.sin_addr.s_addr=htonl(INADDR_ANY);
s_add.sin_port=htons(portnum);
if(-1 == bind(sfp,(struct sockaddr *)(&s_add),
sizeof(struct sockaddr)))
{
printf("bind
fail !\r\n");
return
-1;
}
printf("bind ok !\r\n");
if(-1 == listen(sfp,5))
{
printf("listen fail !\r\n");
return
-1;
}
printf("listen ok\r\n");
while(1)
{
sin_size = sizeof(struct sockaddr_in);
nfp = accept(sfp, (struct sockaddr *)(&c_add),
&sin_size);
if(-1 == nfp)
{
printf("accept fail !\r\n");
return
-1;
}
printf("accept ok!\r\nServer start get connect from %#x :
%#x\r\n",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));
if(-1 == write(nfp,"hello,welcome to my server \r\n",32))
{
printf("write fail!\r\n");
return
-1;
}
printf("write ok!\r\n");
close(nfp);
}
close(sfp);
return 0;
}
在cygwin下,使用gcc命令编译如下:
gcc -o server server.c
gcc -o client client.c
然后运行程序:
./server
./client
server执行效果如下:
Hello,welcome to my server !
socket ok !
bind ok !
listen ok
accept ok!
Server start get connect from 0xc0a80102 : 0xc927
write ok!
client执行效果如下:
Hello,welcome to client !
socket ok !
s_addr = 0x201a8c0 ,port : 0x8888
connect ok !
read ok
REC:
hello,welcome to my server
socket 网摘的更多相关文章
- Delphi 中DataSnap技术网摘
Delphi2010中DataSnap技术网摘 一.为DataSnap系统服务程序添加描述 这几天一直在研究Delphi 2010的DataSnap,感觉功能真是很强大,现在足有理由证明Delphi7 ...
- Feedly订阅Blog部落格RSS网摘 - Blog透视镜
网络信息爆炸的时代,如何更有效率地阅读文章,订阅RSS网摘,可以快速地浏览文章标题,当对某些文章有兴趣时,才点下连结连到原网站,阅读更详细的文章,Feedly Reader阅读器除了提供在线版订阅RS ...
- Bloglines订阅Blog部落格RSS网摘 - Blog透视镜
网络信息蓬勃发展,Blog部落格越来越普及,如果逐一地去浏览网站,势必费时费力,倘若信息可以自己送上门,那就可以节省不少时间,就好像看报纸的标题,有兴趣才点连结,进到网站浏览文章内容,Blogline ...
- TCP/IP协议头部结构体(网摘小结)(转)
源:TCP/IP协议头部结构体(网摘小结) TCP/IP协议头部结构体(转) 网络协议结构体定义 // i386 is little_endian. #ifndef LITTLE_ENDIAN #de ...
- Vim命令快捷键(网摘)
Vim命令快捷键(网摘) 原文出处:[?---->home]
- c#与C++类型转换网摘
转载自 C++和C#转换 https://www.cnblogs.com/zjoch/p/4147182.html c#与C++类型转换,网摘 //c++:HANDLE(void *) ...
- Python入门及容易!网摘分享给大家!
Python:Python学习总结 背景 PHP的$和->让人输入的手疼(PHP确实非常简洁和强大,适合WEB编程),Ruby的#.@.@@也好不到哪里(OO人员最该学习的一门语言). Pyth ...
- PHP实现系统编程(一) --- 网络Socket及IO多路复用【网摘】
一直以来,PHP很少用于socket编程,毕竟是一门脚本语言,效率会成为很大的瓶颈,但是不能说PHP就无法用于socket编程,也不能说PHP的socket编程性能就有多么的低,例如知名的一款PHP ...
- 简单理解php的socket编程【网摘】
php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络 ...
随机推荐
- memcached学习——分布式算法(Consistant hash + 虚拟节点)(三)
1.取余算法 优点:数据分布均匀缺点:当服务器动态的添加.删除节点或者某台server down掉,会导致命中率超大幅度下降,甚至导致服务不可用 2.Consistant Hash算法:一致性哈希算法 ...
- AndroidUI开源组件库BottomView 第三方自定义UI控件
这里分享一个Android的非常经典实用而且简单方便的第三方UI控件库:BottomView(小米的米UI也用到了这个) 原文 http://blog.csdn.net/opzoonzhuzheng ...
- 学习 Netty 3.x
study link: http://netty.io/3.6/guide/#architecture 应用场景: Chat server that requires persistent conne ...
- Ubuntu安装配置Qt环境
安装 QT4.8.6库+QT Creator 2.4.1 下载地址发布 QT4.8.6库 http://mirrors.hustunique.com/qt/official_releases/qt/ ...
- eclipse中安装genymotion
在eclipse中安装genymotion.安装genymotion需要先安装virtualbox.选择Help选项中的install new software 然后点击进去点击ADD,在locati ...
- [c#]asp.net开发微信公众平台(5)微信图文消息
上篇已经成功响应了关注事件,也实现了文本消息的发送,这篇开始图文消息处理, 微信中最常用的消息类型就是图文消息了,因为它图文并茂,最能表达信息. 图文消息在微信中的接口定义如下: <xml> ...
- spring-security 登陆认证之初次探究
首先,希望还对 spring-security框架完全不懂的新手 下载下Git源码. 引入到项目中.这个短文就是边看源码边聊的.也会启动下项目验证自己的推想. 一.登陆认证的登陆配置项 <for ...
- SignalR2.0开发实例之——设置时间、后台其他地方使用集线器、使用自己的连接ID
一.连接的生命周期设置: 如下: // 该值表示连接在超时之前保持打开状态的时间长度. //默认为110秒 GlobalHost.Configuration.ConnectionTimeout = T ...
- bootstrap-datetimepicker使用记录
版本:V2.0 1.bootstrap-datetimepicker.min.css 2.bootstrap-datetimepicker.min.js 3.bootstrap-datetimepic ...
- PM2.5空气质量指数(AQI)是如何计算的
AQI如何计算 具体要计算PM2.5空气质量指数(AQI),SENBE申贝技术人员向您介绍如何计算的公式. 比如当实测浓度小于等于0.035时,根据实测浓度×50/0.035计算.例如 ...