跳至主要内容

【转】VxWorks套接口

int m_socket;
 
// Open a socket
       m_socket = socket(AF_INET, SOCK_STREAM, 0);
 
第一个参数domain说明我们网络程序所在的主机采用的通讯协族(AF_UNIXAF_INET).
AF_UNIX只能够用于单一的Unix系统进程间通信, AF_INET是针对Internet, 因而可以允许在远程主机之间通信.
VxWorks套接字仅支持Internet域地址族, 不支持UNIX域地址族. 因此在需要domain参数的函数中, 使用AF_INET作为函数参数值.
第二个参数type说明我们网络程序所采用的通讯协议(SOCK_STREAM, SOCK_DGRAM). SOCK_STREAM表明我们用的是TCP协议, 这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM 表明我们用的是UDP协议, 这样只会提供定长的,不可靠,无连接的通信.
此外,还有SOCK_RAW代表是原始协议套接字.
第三个参数protocol, 由于我们指定了type, 所以这个地方我们一般只要用0来代替就可以了.
socket为网络通讯做基本的准备, 成功打开则返回一个套接字描述符, 如果失败则返回ERROR.套接字描述符是一个标准的I/O系统文件描述符(fd, file descriptor), 可以被close(), read(), write()ioctl()函数使用.
 
// Make the socket sending alive messages when connected
int flag = 1;
setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(flag));
 
// increase receive buffer size
flag = SOCKET_BUF_SIZE;
setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&flag, sizeof(flag));
 
// increase send buffer size
setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char*)&flag, sizeof(flag));
 
// try without the nagle algorithm
flag = 1;
setsockopt (m_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof (flag));
 
// Prevent "bind error 48"!
flag = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(flag));
 
SOCK_STREAM型套接字支持SO_KEEPALIVE选项,SOCK_DGRAM型套接字不支持。缺省没有启用保活机制。基本套接口选项SO_KEEPALIVE用于检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入。设置该选项后,如果2小时内在此套接口的任一方向都没有数据交换,TCP就自动给对方发一个保持存活探测分节(keep alive probe)。这是一个对方必须响应的TCP分节. 它会导致以下三种情况:对方接收一切正常:以期望的ACK响应。2小时后,TCP将发出另一个探测分节。对方已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESET,套接口本身则被关闭。对方无任何响应:源自berkeleyTCP发送另外8个探测分节,相隔75秒一个,试图得到一个响应。在发出第一个探测分节11分钟15秒后若仍无响应就放弃。套接口的等待处理错误被置为ETIMEOUT,套接口本身则被关闭。如ICMP错误是"host unreachable(主机不可达)",说明对方主机并没有崩溃,但是不可达,这种情况下待处理错误被置为EHOSTUNREACH
 
IPPROTO_TCP: TCP套接口
 
尽管有许多TCP选项可供程序员操作,而我们却最关注如何处置其中的两个选项,它们是TCP_NODELAY TCP_CORK,这两个选项都对网络连接的行为具有重要的作用。
TCP_NODELAYTCP_CORK基本上控制了包的"Nagle"Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。现在让我们假设某个应用程序发出了一个请求,希望发送小块数据。我们可以选择立即发送数据或者等待产生更多的数据然后再一次发送两种策略。如果我们马上发送数据,那么交互性的以及客户/服务器型的应用程序将极大地受益。例如,当我们正在发送一个较短的请求并且等候较大的响应时,相关过载与传输的数据总量相比就会比较低,而且,如果请求立即发出那么响应时间也会快一些。以上操作可以通过设置套接字的TCP_NODELAY选项来完成,这样就禁用了Nagle算法。
 
SO_REUSEADDR选项的设置将套接口设置成重新使用旧的地址(IP地址加端口号)而不等待.
如果一个socket绑定了某个端口,该socket正常关闭或程序退出后,在一段时间内该端口依然保持被绑定的状态,其他程序(或者重新启动的原程序)无法绑定该端口。这由 TCP 套接字状态TIME_WAIT引起。该状态在套接字关闭后约保留 2 4 分钟。在TIME_WAIT状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。等待TIME_WAIT结束可能是令人恼火的一件事,特别是如果您正在开发一个套接字服务器,就需要停止服务器来做一些改动,然后重启。幸运的是,有方法可以避开TIME_WAIT状态。可以给套接字应用SO_REUSEADDR套接字选项,以便端口可以马上重用。
 
// Fill in the address descriptor
struct sockaddr_in addr;                    // 服务器的地址
bzero((char*)&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(Port);                // 默认端口
addr.sin_addr.s_addr = inet_addr(IpAddress);
 
// Bind the socket to the address
bind(m_socket, (struct sockaddr*)&addr, sizeof(addr));
 
// Listen for a client to connect (max n simultaneously)
listen(m_socket, n);
 
在使用TCP协议时,一般服务端任务先使用socket调用得到一个描述符,然后使用bind调用将一个名字与socket描述符连接起来,对于Internet域就是将Internet地址绑定到socket.
之后,服务端使用listen调用指出最大的被拒绝连接次数。然后就可以使用accept调用等待客户端发起连接。
bind函数用于给套接字分配名字。该函数分配一个网络地址(也称为"名字")给指定的套接字,以便其他处理可以连接它或给它发送数据。当使用socket()创建一个套接字时,它属于一个地址族但并没有分配名字。
listen函数允许连接套接字,并指定最大的被拒绝连接次数。当用listen()允许连接后,通过accept()函数接受连接。
一般服务端可能在accept返回后创建一个新的任务进行与客户的通信,或者直接创建一个新的任务来调用accept,原来的任务则继续等待另一个连接。
 

评论

此博客中的热门博文

【转】VxWorks中的地址映射

在运用嵌入式系统VxWorks和MPC860进行通信系统设计开发时,会遇到一个映射地址不能访问的问题。 缺省情况下,VxWorks系统已经进行了如下地址的映射:   memory地址、bcsr(Board Control and Status)地址、PC_BASE_ADRS(PCMCIA)地址、Internal Memory地址、rom(Flach memory)地址等,但是当你的硬件开发中要加上别的外设时,如(falsh、dsp、FPGA等),对这些外设的访问也是通过地址形式进行读写,如果你没有加相应的地址映射,那么是无法访问这些外设的。   和VxWorks缺省地址映射类似,你也可以进行相应的地址映射。   如下是地址映射原理及实现:   1、 地址映射结构 在Tornado\target\h\vmLib.h文件中 typedef struct phys_mem_desc { void *virtualAddr; void *physicalAddr; UINT len; UINT initialStateMask; /* mask parameter to vmStateSet */ UINT initialState; /* state parameter to vmStateSet */ } PHYS_MEM_DESC; virtualAddr:你要映射的虚拟地址 physicalAddr:硬件设计时定义的实际物理地址 len;要进行映射的地址长度 initialStateMask:可以初始化的地址状态: 有如下状态: #define VM_STATE_MASK_VALID 0x03 #define VM_STATE_MASK_WRITABLE 0x0c #define VM_STATE_MASK_CACHEABLE 0x30 #define VM_STATE_MASK_MEM_COHERENCY 0x40 #define VM_STATE_MASK_GUARDED 0x80 不同的CPU芯片类型还有其特殊状态 initialState:实际初始化的地址状态: 有如下状态: #define VM_STATE_VALID 0x01 #define VM_STATE_VALID_NOT 0x00 #define VM_STATE_WRITA

【转】cs8900网卡的移植至基于linux2.6内核的s3c2410平台

cs8900网卡的移植至基于linux2.6内核的s3c2410平台(转) 2008-03-11 20:58 硬件环境:SBC-2410X开发板(CPU:S3C2410X) 内核版本:2.6.11.1 运行环境:Debian2.6.8 交叉编译环境:gcc-3.3.4-glibc-2.3.3 第一部分 网卡CS8900A驱动程序的移植 一、从网上将Linux内核源代码下载到本机上,并将其解压: #tar jxf linux-2.6.11.1.tar.bz2 二、打开内核顶层目录中的Makefile文件,这个文件中需要修改的内容包括以下两个方面。 (1)指定目标平台。 移植前:         ARCH?= $(SUBARCH) 移植后: ARCH            :=arm (2)指定交叉编译器。 移植前: CROSS_COMPILE ?= 移植后: CROSS_COMPILE   :=/opt/crosstool/arm-s3c2410-linux-gnu/gcc-3.3.4-glibc-2.3.3/bin/arm-s3c2410-linux-gnu- 注:这里假设编译器就放在本机的那个目录下。 三、添加驱动程序源代码,这涉及到以下几个方面。(1)、从网上下载了cs8900.c和cs8900.h两个针对2.6.7的内核的驱动程序源代码,将其放在drivers/net/arm/目录下面。 #cp cs8900.c ./drivers/net/arm/ #cp cs8900.h ./drivers/net/arm/ 并在cs8900_probe()函数中,memset (&priv,0,sizeof (cs8900_t));函数之后添加如下两条语句: __raw_writel(0x2211d110,S3C2410_BWSCON); __raw_writel(0x1f7c,S3C2410_BANKCON3); 注:其原因在"第二部分"解释。 (2)、修改drivers/net/arm/目录下的Kconfig文件,在最后添加如下内容: Config ARM_CS8900    tristate "CS8900 support" depends on NET_ETHERNET && A

【转】多迷人Gtkmm啊

前边已经说过用glade设计界面然后动态装载,接下来再来看看怎么改变程序的皮肤(主题)     首先从 http://art.gnome.org/themes/gtk2 下载喜欢的主题,从压缩包里提取gtk-2.0文件夹让它和我们下边代码生成的可执行文件放在同一个目录下,这里我下载的的 http://art.gnome.org/download/themes/gtk2/1317/GTK2-CillopMidnite.tar.gz     然后用glade设计界面,命名为main.glade,一会让它和我们下边代码生成的可执行程序放在同一个目录下边     然后开始写代码如下: //main.cc #include <gtkmm.h> #include <libglademm/xml.h> int main(int argc, char *argv[]) {     Gtk::Main kit(argc,argv);         Gtk::Window *pWnd;        gtk_rc_parse("E:\\theme-viewer\\themes\\gtk-2.0\\gtkrc");       Glib::RefPtr<Gnome::Glade::Xml> refXml;     try     {         refXml = Gnome::Glade::Xml::create("main.glade");     }     catch(const Gnome::Glade::XmlError& ex)     {         Gtk::MessageDialog dialog("Load glade file failed!", false,       \                                   Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);         dialog.run();               return 1;     }         refXml->get_widget("main", pWnd);     if(pW