BSDSocket简易入门手册
目录 介绍
类比 (什么是 socket ?)
装上你的新电话(怎样侦听?)
拨号 (如何调用 socket)
谈话(如何通过 sockets 交谈)
挂起(结束)
世界语(交流的语言很重要)
未来在你的掌握了(下一步?)
--------------------------------------------------------------------------------
介绍
当你进入 UNIX 的神秘世界后,立刻会发现越来越多的东西难以理解。对于大多数人来说,BSD socket 的概念就是其中一个。这是一个很短的教程来解释他们是什么、他们如何工作并给出一些简单的代码来解释如何使用他们。
类比 (什么是 socket ?)
socket 是进行程序间通讯(IPC)的 BSD 方法。这意味着 socket 用来让一个进程和其他的进程互通信息,就象我们用电话来和其他的人交流一样。
用电话来比喻是很恰当的,我们在后面将一直用电话这个概念来描叙 socket 。
装上你的新电话(怎样侦听?)
一个人要能够收到别人打给他的电话,首先他要装上一门电话。同样,你必须先建立 socket 以侦听线路。这个过程包含几个步骤。首先,你要建立一个新的 socket,就象先装上电话一样。socket() 命令就完成这个工作。
因为 sockets 有几种类型,你要注明你要建立什么类型的。你要做一个选择是 socket 的地址格式。如同电话有音频和脉冲两种形式一样,socket 有两个最重要的选项是 AF_UNIX 和 IAF_INET。AF_UNIX 就象 UNIX 路径名一样识别 sockets。这种形式对于在同一台机器上的 IPC 很有用。而 AF_INET 使用象 192.9.200.10 这样被点号隔开的四个十进制数字的地址格式。除了机器地址以外,还可以利用端口号来允许每台机器上的多个 AF_INET socket。我们这里将着重于 AF_INET 方式,因为他很有用并广泛使用。
另外一个你必须提供的参数是 socket 的类型。两个重要的类型是 SOCK_STREAM 和 SOCK_DGRAM。 SOCK_STREAM 表明数据象字符流一样通过 socket 。而 SOCK_DGRAM 则表明数据将是数据报(datagrams)的形式。我们将讲解 SOCK_STREAM sockets,他很常见并易于使用。
在建立 socket 后,我们就要提供 socket 侦听的地址了。就象你还要个电话号码来接电话一样。bind() 函数来处理这件事情。
SOCK_STREAM sockets 让连接请求形成一个队列。如果你忙于处理一个连接,别的连接请求将一直等待到该连接处理完毕。listen() 函数用来设置最大不被拒绝的请求数(一般为5个)。一般最好不要使用 listen() 函数。
下面的代码说明如何利用 socket()、 bind() 和 listen() 函数建立连接并可以接受数据。
/* code to establish a socket; originally from bzs@bu-cs.bu.edu
*/
int establish(unsigned short portnum)
{ char myname[MAXHOSTNAME+1];
int s;
struct sockaddr_in sa;
struct hostent *hp;
memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
gethostname(myname, MAXHOSTNAME); /* who are we? */
hp= gethostbyname(myname); /* get our address info */
if (hp == NULL) /* we don't exist !? */
return(-1);
sa.sin_family= hp->h_addrtype; /* this is our host address */
sa.sin_port= htons(portnum); /* this is our port number */
if ((s= socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
return(-1);
if (bind(s,&sa,sizeof(struct sockaddr_in)) < 0) {
close(s);
return(-1); /* bind address to socket */
}
listen(s, 3); /* max # of queued connects */
return(s);
}
在建立完 socket 后,你要等待对该 socket 的调用了。accept() 函数为此目的而来。调用 accept() 如同在电话铃响后提起电话一样。Accept() 返回一个新的连接到调用方的 socket 。
下面的代码演示使用是个演示。
/* wait for a connection to occur on a socket created with establish()
*/
int get_connection(int s)
{ int t; /* socket of connection */
if ((t = accept(s,NULL,NULL)) < 0) /* accept connection if there is one */
return(-1);
return(t);
}
和电话不同的是,在你处理先前的连接的时候,你还可以接受调用。为此,一般用 fork 来处理每个连接。下面的代码演示如何使用 establish() 和 get_connection() 来处理多个连接。
#include <errno.h> /* obligatory includes */
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORTNUM 50000 /* random port number, we need something */
void fireman(void);
void do_something(int);
main()
{ int s, t;
if ((s= establish(PORTNUM)) < 0) { /* plug in the phone */
perror("establish");
exit(1);
}
signal(SIGCHLD, fireman); /* this eliminates zombies */
for (;;) { /* loop for phone calls */
if ((t= get_connection(s)) < 0) { /* get a connection */
if (errno == EINTR) /* EINTR might happen on accept(), */
continue; /* try again */
perror("accept"); /* bad */
exit(1);
}
switch(fork()) { /* try to handle connection */
case -1 : /* bad news. scream and die */
perror("fork");
close(s);
close(t);
exit(1);
case 0 : /* we're the child, do something */
close(s);
do_something(t);
exit(0);
default : /* we're the parent so look for */
close(t); /* another connection */
continue;
}
}
}
/* as children die we should get catch their returns or else we get
* zombies, A Bad Thing. fireman() catches falling children.
*/
void fireman(void)
{
while (waitpid(-1, NULL, WNOHANG) > 0)
;
}
/* this is the function that plays with the socket. it will be called
* after getting a connection.
*/
void do_something(int s)
{
/* do your thing with the socket here
:
:
*/
}
拨号 (如何调用 socket)
现在你应该知道如何建立 socket 来接受调用了。那么如何调用呢?和电话一样,你要先有个电话。用 socket() 函数来完成这件事情,就象建立侦听的 socket 一样。
在给 socket 地址后,你可以用 connect() 函数来连接侦听的 socket 了。下面是一段代码。
int call_socket(char *hostname, unsigned short portnum)
{ struct sockaddr_in sa;
struct hostent *hp;
int a, s;
if ((hp= gethostbyname(hostname)) == NULL) { /* do we know the host's */
errno= ECONNREFUSED; /* address? */
return(-1); /* no */
}
memset(&sa,0,sizeof(sa));
memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length); /* set address */
sa.sin_family= hp->h_addrtype;
sa.sin_port= htons((u_short)portnum);
if ((s= socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) /* get socket */
return(-1);
if (connect(s,&sa,sizeof sa) < 0) { /* connect */
close(s);
return(-1);
}
return(s);
}
这个函数返回一个可以流过数据的 socket 。
谈话(如何通过 sockets 交谈)
好了,你在要传输数据的双方建立连接了,现在该传输数据了。read() 和 write() 函数来处理吧。除了在 socket 读写和文件读写中的一个区别外,和处理一般的文件一样。区别是你一般不能得到你所要的数目的数据。所以你要一直循环到你需要的数据的到来。一个简单的例子:将一定的数据读到缓存。
int read_data(int s, /* connected socket */
char *buf, /* pointer to the buffer */
int n /* number of characters (bytes) we want */
)
{ int bcount; /* counts bytes read */
int br; /* bytes read this pass */
bcount= 0;
br= 0;
while (bcount < n) { /* loop until full buffer */
if ((br= read(s,buf,n-bcount)) > 0) {
bcount += br; /* increment byte counter */
buf += br; /* move buffer ptr for next read */
}
else if (br < 0) /* signal an error to the caller */
return(-1);
}
return(bcount);
}
相同的函数也可以写数据,留给我们的读者吧。
挂起(结束)
和你通过电话和某人交谈后一样,你要在 socket 间关闭连接。一般 close() 函数用来关闭每边的 socket 连接。如果一边的已经关闭,而另外一边却在向他写数据,则返回一个错误代码。
世界语(交流的语言很重要)
现在你可以在机器间联络了,可是要小心你所说的话。许多机器有自己的方言,如 ASCII 和 EBCDIC。更常见的问题是字节顺序问题。除非你一直传输的都是文本,否则你一定要注意这个问题。幸运的是,人们找出了解决的办法。
在很久以前,人们争论哪种顺序更“正确”。现在必要时有相应的函数来转换。其中有 htons()、ntohs()、htonl() 和 ntohl()。在传输一个整型数据前,先转换一下。
i= htonl(i);
write_data(s, &i, sizeof(i));
在读数据后,再变回来。
read_data(s, &i, sizeof(i));
i= ntohl(i);
如果你一直坚持这个习惯,你将比别人少出错的机会。
未来在你的掌握了(下一步?)
就用我们刚才讨论的东西,你就可以写自己的通讯程序了。和对待所有的新生事物一样, 最好还是看看别人已经做了些什么。这里有许多关于 BSD socket 的东西可以参考。
请注意,例子中没有错误检查,这在“真实”的程序中是很重要的。你应该对此充分重视。
from:
http://www.douzhe.com/mirrors/fanqiang.com/a4/b7/20010821/0900001157.html
分享到:
相关推荐
BSD Socket 简易入门教程旨在为初学者提供关于Linux下Socket编程的基础知识。Socket编程是一种在不同进程间实现通信的技术,特别是在Unix和类Unix系统中广泛应用。在本教程中,我们将通过类比电话的方式,逐步解析...
【winsocket - BSD socket 入门讲义】 在IT领域,网络编程是不可或缺的一部分,而Winsock(Windows Socket)和BSD Socket是其中两种常见的API,用于实现跨平台的TCP/IP网络通信。本讲义主要围绕这两者的基础知识...
在iOS开发中,为了实现设备间的网络通信,开发者经常需要用到BSD Socket接口。BSD(Berkeley Software Distribution)Socket是UNIX系统中广泛使用的网络编程接口,它也在iOS操作系统中得到了支持。本篇文章将深入...
根据提供的文件信息,“BSD Socket Interface Programmer’s Guide Edition 6”主要介绍了Unix/Linux环境下BSD套接字编程的相关知识。下面将详细解析此文档所涉及的重要知识点。 ### 一、BSD Socket 接口概述 ####...
cocos2d-x c++ BSD Socket.
标题《iPhone网络通讯之BSD Socket篇》所涉及的知识点主要集中在iOS开发中网络编程的基础,具体到BSD套接字(BSD Socket)的应用。BSD套接字是网络编程中使用的一套API,用于实现进程间的通信(IPC),也可以用于...
在iOS开发中,BSD Sockets是用于网络通信的基础接口,它们...总的来说,iOS上的BSD Socket客户端编程涉及网络连接的建立、数据的发送与接收以及异常处理等多个方面,熟练掌握这些技术对于开发网络应用程序至关重要。
Objective-C 实现 TCP 通信通常涉及到使用底层的 BSD socket API 或者使用更高级别的网络框架,如 NSStream。附件是一个使用 BSD socket API 实现 TCP 客户端和服务器的基本示例。 请注意,这些代码是基础的 BSD ...
本模块主要关注的是如何在Cocos2d-x环境中使用基于BSD Socket的网络通信技术。下面将详细阐述相关知识点。 首先,我们来了解**BSD Socket**。BSD Socket是Berkeley Software Distribution(BSD)系统中引入的一种...
本资源内含两个demo:SocketServer服务器端,SocketClient客户端 Socket客户端和服务器端通信,是个难点,这两个项目里面有详细的中文注释,并且能完美运行。为了使后来人能更快的掌握ios开发,本人将这个资源发布到...
在BSD Socket中,创建一个Socket需要使用socket函数,它的一般形式为:int socket(int domain, int type, int protocol); domain参数决定Socket使用的地址族,例如AF_INET代表IPv4互联网地址族,而AF_UNIX则用于本地...
做做COCOS2D-X发现了3三方库严重缺少,于是很无奈的情况下写点东西,希望对大家有帮助,实现了文件上传HTTP和文件下载的过程,终于遇到了很多问题,以及BSD SOCKET做连接封装好的库提供给大家,支持WIN32 UNIX LINUX...
标题中的“Network的bsd socket的ipv6可以连接服务器3344,可以接受数据”意味着在iOS平台上,使用BSD Socket接口实现的网络编程能够成功地通过IPv6协议连接到一个服务器,该服务器的端口号是3344,并且能够进行数据...
提供的压缩包文件"cocos2dxBSD_Socket"可能包含了示例代码,展示了如何在Cocos2d-x项目中使用BSD Sockets进行网络通信。这些示例可能涵盖了从创建socket到数据交换的整个流程,有助于学习和理解。 通过以上知识,...
《lib-Network:基于BSD Socket的跨平台多线程网络库在C++中的实现与应用》 在现代软件开发中,网络通信是不可或缺的一部分,尤其是在游戏开发领域。lib-Network库是一个专门针对Cocos2d-x游戏开发设计的、基于BSD ...
实验六的目的是让学生掌握Linux BSD Socket编程,实现以太帧的捕获与分析,从而能够实时监测网络中传输的数据帧并理解其结构。这个实验主要分为以下几个知识点: 1. **以太网数据帧格式**:以太帧由目标MAC地址、源...
BSDSocket相关: 若干文档,若干代码。 NetCommandHelper* NetCommandHelper::getInstance() { static NetCommandHelper* s_netCommandHelper = nullptr; if (s_netCommandHelper == nullptr) { s_...
The Design and Implementation of the 4.4BSD Operating System Marshall Kirk McKusick Keith Bostic Michael J. Karels John S. Quarterman Copyright © 1996 Addison-Wesley Longman, Inc The second ...
Socket的Keepalive机制是TCP/IP通信中用于保持连接活跃性的一种技术。它的主要目标是确保在TCP连接上,即使在长时间无数据交换的情况下,也能检测到连接是否仍然有效。这在服务器与客户端通信中尤其重要,因为如果...