socket编程基础


1 Socket 提供 的系 统调 用或 函数 提供 的系 统调 用或 函数 提供 的系 统调 用或 函数 提供 的系 统调 用或 函数 比如通讯过程中每次读多少字节,以什么表示结束 就两个任务吧,就是把现在对字符串的处理,再分别用消息队列通讯的方式实现和 shell 脚本实现 socket() 获得一个 socket 文件描述符 bind 将指定 socket 绑定到某端口 connect 连接到远程某个端口 listen() 侦听等待远程连接 accept() 接受了一个远程连接 send(),recv() 发送或接收数据(TCP) sendto(),recvfrom() 发送或接收数据(UDP) close() 关闭 socket 描述符 shutdown() 改变 socket 可用性 getpeername() 获得连接另外一端的地址信息 gethostname() 获得本机主机名 gethostbyname() 根据主机名得到主机地址信息 inet_addr() 将IP 地址字符串转换成网络字节序的 4字 节地址 2 客客客客 户户户户 机机机机 / 服服服服 务务务务 器器器器 模模模模 式式式式 3 Socket 编程 基础 重要 的数 据结 构 编程 基础 重要 的数 据结 构 编程 基础 重要 的数 据结 构 编程 基础 重要 的数 据结 构 3.13.13.13.1 sockaddr sockaddr sockaddr sockaddr 结构,存放各种 结构,存放各种 结构,存放各种 结构,存放各种 socket socket socket socket 的地址信息 的地址信息 的地址信息 的地址信息 struct sockaddr { unsigned short sa_family;// address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address };//总长度 16 字节 3.23.23.23.2 sockaddr_insockaddr_insockaddr_insockaddr_in,存放 ,存放 ,存放 ,存放 InternetInternetInternetInternet socket socket socket socket 地址信息 地址信息 地址信息 地址信息 struct sockaddr_in { short int sin_family;// Address family unsigned short int sin_port;// Port number struct in_addr sin_addr;// Internet address unsigned char sin_zero[8]; // Same size as struct sockaddr }; struct in_addr { uint32_t s_addr;// that's a 32-bit int (4 bytes) }; 4 Socket 提供 的系 统调 用或 函数 的详 细讲 解 提供 的系 统调 用或 函数 的详 细讲 解 提供 的系 统调 用或 函数 的详 细讲 解 提供 的系 统调 用或 函数 的详 细讲 解 4.14.14.14.1 socketsocketsocketsocket(建立一个 (建立一个 (建立一个 (建立一个 socket socket socket socket 通信) 通信) 通信) 通信) 相关函数 accept,bind,connect,listen 表头文件 #include #include 定义函数 int socket(int domain,int type,int protocol); 函数说明 socket()用来建立一个新的 socket,也就是向系统注册, 通知系统建立一通信端口。参数 domain 指定使用何种的地址类型,完整的定义 在/usr/include/bits/socket.h 内,底下是常见的协议: PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL UNIX 进程通信协议 PF_INET?AF_INET Ipv4 网络协议 PF_INET6/AF_INET6 Ipv6 网络协议 PF_IPX/AF_IPX IPX-Novell 协议 PF_NETLINK/AF_NETLINK 核心用户接口装置 PF_X25/AF_X25 ITU-T X.25/ISO-8208 协议 PF_AX25/AF_AX25 业余无线 AX.25 协议 PF_ATMPVC/AF_ATMPVC 存取原始 ATM PVCs PF_APPLETALK/AF_APPLETALK appletalk(DDP)协议 PF_PACKET/AF_PACKET 初级封包接口 参数 type 有下列几种数值: SOCK_STREAM 提供双向连续且可信赖的数据流,即TCP。支持 OOB 机制, 在所有数据传送前必须使用 connect()来建立连线状态。 SOCK_DGRAM 使用不连续不可信赖的数据包连接 SOCK_SEQPACKET 提供连续可信赖的数据包连接 SOCK_RAW 提供原始网络协议存取 SOCK_RDM 提供可信赖的数据包连接 SOCK_PACKET 提供和网络驱动程序直接通信。 protocol 用来指定 socket 所使用的传输协议编号,通常此参考不用管 它,设为 0即可。 返回值 成功则返回 socket 处理代码,失败返回-1。 错误代码 EPROTONOSUPPORT 参数 domain 指定的类型不支持参数 type 或protocol 指定的协议 ENFILE 核心内存不足,无法建立新的 socket 结构 EMFILE 进程文件表溢出,无法再建立新的 socket EACCESS 权限不足,无法建立 type 或protocol 指定的协议 ENOBUFS/ENOMEM 内存不足 EINVAL 参数 domain/type/protocol 不合法 范例 参考connect()。 4.24.24.24.2 bindbindbindbind(对 (对 (对 (对 socket socket socket socket 定位) 定位) 定位) 定位) 相关函数 socket,accept,connect,listen 表头文件 #include #include 定义函数 int bind(int sockfd,struct sockaddr * my_addr,int addrlen); 函数说明 bind()用来设置给参数 sockfd 的socket 一个名称。此名称由参数 my_addr 指向一 sockaddr 结构,对于不同的 socket domain 定义了一个通用的数据结构 struct sockaddr { unsigned short int sa_family; char sa_data[14]; }; sa_family 为调用 socket()时的 domain 参数,即 AF_xxxx 值。 sa_data 最多使用 14个字符长度。 此sockaddr 结构会因使用不同的 socket domain 而有不同结构定义,例如使用 AF_INET domain,其socketaddr 结构定义便为 struct socketaddr_in { unsigned short int sin_family; uint16_t sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; struct in_addr { uint32_t s_addr; }; sin_family 即为sa_family sin_port 为使用的 port 编号 sin_addr.s_addr 为IP 地址 sin_zero 未使用。 参数 addrlen 为sockaddr 的结构长度。 返回值 成功则返回 0,失败返回-1,错误原因存于 errno 中。 错误代码 EBADF 参数sockfd 非合法 socket 处理代码。 EACCESS 权限不足 ENOTSOCK 参数sockfd 为一文件描述词,非 socket。 范例 参考listen() 4.34.34.34.3 listenlistenlistenlisten(等待连接) (等待连接) (等待连接) (等待连接) 相关函数 socket,bind,accept,connect 表头文件 #include 定义函数 int listen(int s,int backlog); 函数说明 listen()用来等待参数 s 的socket 连线。参数backlog 指定同时能处 理的最大连接要求,如果连接数目达此上限则 client 端将收到 ECONNREFUSED 的错误。 Listen()并未开始接收连线,只是设置 socket 为listen 模式,真正接收 client 端连线的 是accept()。通常 listen()会在socket(),bind()之后调用,接着才调用 accept()。 返回值 成功则返回 0,失败返回-1,错误原因存于 errno 附加说明 listen()只适用 SOCK_STREAM 或SOCK_SEQPACKET 的socket 类型。如果 socket 为AF_INET 则参数 backlog 最大值可设至 128。 错误代码 EBADF 参数sockfd 非合法 socket 处理代码 EACCESS 权限不足 EOPNOTSUPP 指定的 socket 并未支援 listen 模式。 4.44.44.44.4 acceptacceptacceptaccept(接受 (接受 (接受 (接受 socket socket socket socket 连连连连接接接接)))) 相关函数 socket,bind,listen,connect 表头文件 #include #include 定义函数 int accept(int s,struct sockaddr * addr,int * addrlen); 函数说明 accept()用来接受参数 s 的 socket 连接。参数 s 的 socket 必需先经 bind()、listen() 函数处理过,当有连接进来时 accept()会返回一个新的 socket 处理代码,往后的数据传送与读取就是经 由新的 socket 处理,而原来参数 s的socket 能继续使用 accept()来接受新的连接要求。连接成功时,参 数addr 所指的结构会被系统填入远程主机的地址数据,参数 addrlen 为scokaddr 的结构长度。关于结构 sockaddr 的定义请参考 bind()。 返回值 成功则返回新的 socket 处理代码,失败返回-1,错误原因存于 errno 中。 错误代码 EBADF 参数 s 非合法 socket 处理代码。 EFAULT 参数 addr 指针指向无法存取的内存空间。 ENOTSOCK 参数 s为一文件描述词,非 socket。 EOPNOTSUPP 指定的 socket 并非 SOCK_STREAM。 EPERM 防火墙拒绝此连线。 ENOBUFS 系统的缓冲内存不足。 ENOMEM 核心内存不足。 4.54.54.54.5 recvrecvrecvrecv(经 (经 (经 (经 socket socket socket socket 接收数据) 接收数据) 接收数据) 接收数据) 相关函数 recvfrom,recvmsg,send,sendto,socket 表头文件 #include #include 定义函数 int recv(int s,void *buf,int len,unsigned int flags); 函数说明 recv()用来接收远端主机经指定的 socket 传来的数据,并 把数据存到由参数 buf 指向的内存空间,参数 len 为可接收数据的最大长度。 参数 flags 一般设 0。其他数值定义如下: MSG_OOB 接收以 out-of-band 送出的数据。 MSG_PEEK 返回来的数据并不会在系统内删除,如果再调用 recv()会返 回相同的数据内容。 MSG_WAITALL 强迫接收到 len 大小的数据后才能返回,除非有错误或信 号产生。 MSG_NOSIGNAL 此操作不愿被 SIGPIPE 信号中断返回值成功则返回接收 到的字符数,失败返回-1,错误原因存于 errno 中。 错误代码 EBADF 参数 s非合法的 socket 处理代码 EFAULT 参数中有一指针指向无法存取的内存空间 ENOTSOCK 参数 s为一文件描述词,非 socket。 EINTR 被信号所中断 EAGAIN 此动作会令进程阻断,但参数 s的socket 为不可阻断 ENOBUFS 系统的缓冲内存不足。 ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确。 范例 参考 listen()。 4.64.64.64.6 recvfromrecvfromrecvfromrecvfrom(经 (经 (经 (经 socket socket socket socket 接收数据) 接收数据) 接收数据) 接收数据) 相关函数 recv,recvmsg,send,sendto,socket 表头文件 #include #include 定义函数 int recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen); 函数说明 recv()用来接收远程主机经指定的 socket 传来的数据,并 把数据存到由参数 buf 指向的内存空间,参数 len 为可接收数据的最大长度。 参数 flags 一般设 0,其他数值定义请参考 recv()。参数 from 用来指定欲传送 的网络地址,结构 sockaddr 请参考 bind()。参数 fromlen 为sockaddr 的结构 长度。 返回值 成功则返回接收到的字符数,失败则返回-1,错误原因存于 errno 中。 错误代码 EBADF 参数 s非合法的 socket 处理代码 EFAULT 参数中有一指针指向无法存取的内存空间。 ENOTSOCK 参数 s为一文件描述词,非 socket。 EINTR 被信号所中断。 EAGAIN 此动作会令进程阻断,但参数 s的socket 为不可阻断。 ENOBUFS 系统的缓冲内存不足 ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确。 范例 /*利用 socket 的UDP client 此程序会连线 UDP server,并将键盘输入的字符串传给 server。 UDP server 范例请参考 sendto()。 */ #include #include #include #include #include #include #include #define PORT 2345 #define SERVER_IP “127.0.0.1” main() { int s,len; struct sockaddr_in addr; int addr_len =sizeof(struct sockaddr_in); char buffer[256]; /* 建立 socket*/ if((s = socket(AF_INET,SOCK_DGRAM,0))<0){ perror(“socket”); exit(1); } /* 填写 sockaddr_in*/ bzero(&addr,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = inet_addr(SERVER_IP); while(1){ bzero(buffer,sizeof(buffer)); /* 从标准输入设备取得字符串*/ len =read(STDIN_FILENO,buffer,sizeof(buffer)); /* 将字符串传送给 server 端*/ sendto(s,buffer,len,0,&addr,addr_len); /* 接收 server 端返回的字符串*/ len = recvfrom(s,buffer,sizeof(buffer),0,&addr,&addr_len); printf(“receive: %s”,buffer); } } 执行 (先执行 udp server 再执行 udp client) hello /*从键盘输入字符串*/ receive: hello /*server 端返回来的字符串*/ 4.74.74.74.7 recvmsgrecvmsgrecvmsgrecvmsg(经 (经 (经 (经 socket socket socket socket 接收数据) 接收数据) 接收数据) 接收数据) 相关函数 recv,recvfrom,send,sendto,sendmsg,socket 表头文件 #include #include 定义函数 int recvmsg(int s,struct msghdr *msg,unsigned int flags); 函数说明 recvmsg()用来接收远程主机经指定的 socket 传来的数据。 参数 s为已建立好连线的 socket,如果利用 UDP 协议则不需经过连线操作。参 数msg 指向欲连线的数据结构内容,参数 flags 一般设 0,详细描述请参考 send()。关于结构 msghdr 的定义请参考 sendmsg()。 返回值 成功则返回接收到的字符数,失败则返回-1,错误原因存于 errno 中。 错误代码 EBADF 参数 s非合法的 socket 处理代码。 EFAULT 参数中有一指针指向无法存取的内存空间 ENOTSOCK 参数 s为一文件描述词,非 socket。 EINTR 被信号所中断。 EAGAIN 此操作会令进程阻断,但参数 s的socket 为不可阻断。 ENOBUFS 系统的缓冲内存不足 ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确。 范例 参考 recvfrom()。 4.84.84.84.8 sendsendsendsend(经 (经 (经 (经 socket socket socket socket 传送数据) 传送数据) 传送数据) 传送数据) 相关函数 sendto,sendmsg,recv,recvfrom,socket 表头文件 #include #include 定义函数 int send(int s,const void * msg,int len,unsigned int falgs); 函数说明 send()用来将数据由指定的 socket 传给对方主机。参数 s 为已建立好连接的 socket。参数 msg 指向欲连线的数据内容,参数 len 则为数 据长度。参数 flags 一般设 0,其他数值定义如下 MSG_OOB 传送的数据以 out-of-band 送出。 MSG_DONTROUTE 取消路由表查询 MSG_DONTWAIT 设置为不可阻断运作 MSG_NOSIGNAL 此动作不愿被 SIGPIPE 信号中断。 返回值 成功则返回实际传送出去的字符数,失败返回-1。错误原因存 于errno 错误代码 EBADF 参数 s 非合法的 socket 处理代码。 EFAULT 参数中有一指针指向无法存取的内存空间 ENOTSOCK 参数 s为一文件描述词,非 socket。 EINTR 被信号所中断。 EAGAIN 此操作会令进程阻断,但参数 s的socket 为不可阻断。 ENOBUFS 系统的缓冲内存不足 ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确。 范例 参考 connect() 4.94.94.94.9 sendmsgsendmsgsendmsgsendmsg(经 (经 (经 (经 socket socket socket socket 传送数据) 传送数据) 传送数据) 传送数据) 相关函数 send,sendto,recv,recvfrom,recvmsg,socket 表头文件 #include #include 定义函数 int sendmsg(int s,const strcut msghdr *msg,unsigned int flags); 函数说明 sendmsg()用来将数据由指定的 socket 传给对方主机。参数 s为已建立好连线的 socket,如果利用 UDP 协议则不需经过连线操作。参数 msg 指向欲连线的数据结构内容,参数 flags 一般默认为 0,详细描述请参考 send()。 结构 msghdr 定义如下 struct msghdr { void *msg_name; /*Address to send to /receive from .*/ socklen_t msg_namelen; /* Length of addres data */ strcut iovec * msg_iov; /* Vector of data to send/receive into */ size_t msg_iovlen; /* Number of elements in the vector */ void * msg_control; /* Ancillary dat */ size_t msg_controllen; /* Ancillary data buffer length */ int msg_flags; /* Flags on received message */ }; 返回值 成功则返回实际传送出去的字符数,失败返回-1,错误原因存 于errno 错误代码 EBADF 参数 s 非合法的 socket 处理代码。 EFAULT 参数中有一指针指向无法存取的内存空间 ENOTSOCK 参数 s为一文件描述词,非 socket。 EINTR 被信号所中断。 EAGAIN 此操作会令进程阻断,但参数 s的socket 为不可阻断。 ENOBUFS 系统的缓冲内存不足 ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确。 范例 参考 sendto()。 4.104.104.104.10 sendtosendtosendtosendto(经 (经 (经 (经 socket socket socket socket 传送数据) 传送数据) 传送数据) 传送数据) 相关函数 send , sendmsg,recv , recvfrom , socket 表头文件 #include < sys/types.h > #include < sys/socket.h > 定义函数 int sendto ( int s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen ); 函数说明 sendto() 用来将数据由指定的 socket 传给对方主机。参数 s为已建好连线的 socket,如果利用 UDP 协议则不需经过连线操作。参数 msg 指 向欲连线的数据内容,参数 flags 一般设 0,详细描述请参考 send()。参数 to 用来指定欲传送的网络地址,结构 sockaddr 请参考 bind()。参数 tolen 为 sockaddr 的结果长度。 返回值 成功则返回实际传送出去的字符数,失败返回-1,错误原因 存于 errno 中。 错误代码 EBADF 参数 s非法的 socket 处理代码。 EFAULT 参数中有一指针指向无法存取的内存空间。 WNOTSOCK canshu s为一文件描述词,非 socket。 EINTR 被信号所中断。 EAGAIN 此动作会令进程阻断,但参数 s的soket 为补课阻断的。 ENOBUFS 系统的缓冲内存不足。 EINVAL 传给系统调用的参数不正确。 范例 #include < sys/types.h > #include < sys/socket.h > # include #include #define PORT 2345 /*使用的 port*/ main(){ int sockfd,len; struct sockaddr_in addr; char buffer[256]; /*建立 socket*/ if(sockfd=socket (AF_INET,SOCK_DGRAM,0))<0){ perror (“socket”); exit(1); } /*填写 sockaddr_in 结构*/ bzero (&addr, sizeof(addr) ); addr.sin_family=AF_INET; addr.sin_port=htons(PORT); addr.sin_addr=hton1(INADDR_ANY) ; if (bind(sockfd, &addr, sizeof(addr))<0){ perror(“connect”); exit(1); } while(1){ bezro(buffer,sizeof(buffer)); len = recvfrom(socket,buffer,sizeof(buffer), 0 ,&addr &addr_len); /*显示 client 端的网络地址*/ printf(“receive from %s\n “, inet_ntoa( addr.sin_addr)); /*将字串返回给 client 端*/ sendto(sockfd,buffer,len,0,&addr,addr_len);” } } 执行 请参考 recvfrom() 4.114.114.114.11setprotoentsetprotoentsetprotoentsetprotoent(打开网络协议的数据文件) (打开网络协议的数据文件) (打开网络协议的数据文件) (打开网络协议的数据文件) 相关函数 getprotobyname, getprotobynumber, endprotoent 表头文件 #include 定义函数 void setprotoent (int stayopen); 函数说明 setprotoent()用来打开/etc/protocols, 如果参数 stayopen 值为 1,则接下来的 getprotobyname()或getprotobynumber()将不会 自动关闭此文件。 setservent(打开主机网络服务的数据文件) 相关函数 getservent, getservbyname, getservbyport, endservent 表头文件 #include < netdb.h > 定义函数 void setservent (int stayopen); 函数说明 setservent()用来打开/etc/services,如果参数 stayopen 值为 1,则接下来的 getservbyname()或getservbyport()将补回自动关闭文件。 4.124.124.124.12 setsockoptsetsockoptsetsockoptsetsockopt(设置 (设置 (设置 (设置 socket socket socket socket 状态) 状态) 状态) 状态) 相关函数 getsockopt 表头文件 #include #include 定义函数 int setsockopt(int s,int level,int optname,const void * optval,,socklen_toptlen); 函数说明 setsockopt()用来设置参数 s所指定的 socket 状态。参数 level 代表欲设置的网络层,一般设成 SOL_SOCKET 以存取 socket 层。参数 optname 代表欲设置的选项,有下列几种数值: SO_DEBUG 打开或关闭排错模式 SO_REUSEADDR 允许在 bind()过程中本地地址可重复使用 SO_TYPE 返回 socket 形态。 SO_ERROR 返回 socket 已发生的错误原因 SO_DONTROUTE 送出的数据包不要利用路由设备来传输。 SO_BROADCAST 使用广播方式传送 SO_SNDBUF 设置送出的暂存区大小 SO_RCVBUF 设置接收的暂存区大小 SO_KEEPALIVE 定期确定连线是否已终止。 SO_OOBINLINE 当接收到 OOB 数据时会马上送至标准输入设备 SO_LINGER 确保数据安全且可靠的传送出去。 参数 optval 代表欲设置的值,参数 optlen 则为 optval 的长度。 返回值 成功则返回 0,若有错误则返回-1,错误原因存于 errno。 附加说明 EBADF 参数 s并非合法的 socket 处理代码 ENOTSOCK 参数 s为一文件描述词,非 socket ENOPROTOOPT 参数 optname 指定的选项不正确。 EFAULT 参数 optval 指针指向无法存取的内存空间。 范例 参考 getsockopt()。 4.134.134.134.13 shutdownshutdownshutdownshutdown(终止 (终止 (终止 (终止 socket socket socket socket 通信) 通信) 通信) 通信) 相关函数 socket,connect 表头文件 #include 定义函数 int shutdown(int s,int how); 函数说明 shutdown()用来终止参数 s所指定的 socket 连线。参数 s 是连线中的 socket 处理代码,参数 how 有下列几种情况: how=0 终止读取操作。 how=1 终止传送操作 how=2 终止读取及传送操作 返回值 成功则返回 0,失败返回-1,错误原因存于 errno。 错误代码 EBADF 参数 s不是有效的 socket 处理代码 ENOTSOCK 参数 s为一文件描述词,非 socket ENOTCONN 参数 s指定的 socket 并未连线 4.144.144.144.14 ntohlntohlntohlntohl((((将将将将32 32 32 32 位网络字符顺序转换成主机字符顺 位网络字符顺序转换成主机字符顺 位网络字符顺序转换成主机字符顺 位网络字符顺序转换成主机字符顺 序) 序) 序) 序) 相关函数 htonl,htons,ntohs 表头文件 #include 定义函数 unsigned long int ntohl(unsigned long int netlong); 函数说明 ntohl()用来将参数指定的32位 netlong 转换成主机字符顺 序。 返回值 返回对应的主机字符顺序。 范例 参考 getservent()。 4.154.154.154.15 ntohsntohsntohsntohs(将 (将 (将 (将 16 16 16 16 位网络字符顺序转换成主机字符 位网络字符顺序转换成主机字符 位网络字符顺序转换成主机字符 位网络字符顺序转换成主机字符 顺序) 顺序) 顺序) 顺序) 相关函数 htonl,htons,ntohl 表头文件 #include 定义函数 unsigned short int ntohs(unsigned short int netshort); 函数说明 ntohs()用来将参数指定的 16 位netshort 转换成主机字符 顺序。 返回值 返回对应的主机顺序。 范例 参考 getservent()。 4.164.164.164.16 connectconnectconnectconnect(建立 (建立 (建立 (建立 socket socket socket socket 连线) 连线) 连线) 连线) 相关函数 socket,bind,listen 表头文件 #include #include 定义函数 int connect (int sockfd,struct sockaddr * serv_addr,int addrlen); 函数说明 connect()用来将参数 sockfd 的socket 连至参数 serv_addr 指定的网络地址。结构 sockaddr 请参考 bind()。参数 addrlen 为 sockaddr 的结构长度。 返回值 成功则返回 0,失败返回-1,错误原因存于 errno 中。 错误代码 EBADF 参数 sockfd 非合法 socket 处理代码 EFAULT 参数 serv_addr 指针指向无法存取的内存空间 ENOTSOCK 参数 sockfd 为一文件描述词,非 socket。 EISCONN 参数 sockfd 的socket 已是连线状态 ECONNREFUSED 连线要求被 server 端拒绝。 ETIMEDOUT 企图连线的操作超过限定时间仍未有响应。 ENETUNREACH 无法传送数据包至指定的主机。 EAFNOSUPPORT sockaddr 结构的 sa_family 不正确。 EALREADY socket 为不可阻断且先前的连线操作还未完成。 范例 /* 利用 socket 的TCP client 此程序会连线 TCP server,并将键盘输入的字符串传送给 server。 TCP server 范例请参考 listen()。 */ #include #include #include #include #include #include #include #define PORT 1234 #define SERVER_IP “127.0.0.1” main() { int s; struct sockaddr_in addr; char buffer[256]; if((s = socket(AF_INET,SOCK_STREAM,0))<0){ perror(“socket”); exit(1); } /* 填写 sockaddr_in 结构*/ bzero(&addr,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port=htons(PORT); addr.sin_addr.s_addr = inet_addr(SERVER_IP); /* 尝试连线*/ if(connect(s,&addr,sizeof(addr))<0){ perror(“connect”); exit(1); } /* 接收由 server 端传来的信息*/ recv(s,buffer,sizeof(buffer),0); printf(“%s\n”,buffer); while(1){ bzero(buffer,sizeof(buffer)); /* 从标准输入设备取得字符串*/ read(STDIN_FILENO,buffer,sizeof(buffer)); /* 将字符串传给 server 端*/ if(send(s,buffer,sizeof(buffer),0)<0){ perror(“send”); exit(1); } } } 执行 $ ./connect Welcome to server! hi I am client! /*键盘输入*/ /*中断程序*/ 4.174.174.174.17 endprotoentendprotoentendprotoentendprotoent(结束网络 (结束网络 (结束网络 (结束网络 协议 协议 协议 协议 数据的读取) 数据的读取) 数据的读取) 数据的读取) 相关函数 getprotoent,getprotobyname,getprotobynumber, setprotoent 表头文件 #include 定义函数 void endprotoent(void); 函数说明 endprotoent()用来关闭由 getprotoent()打开的文件。 返回值 范例 参考 getprotoent() 4.184.184.184.18 endserventendserventendserventendservent(结束网络服务数据的读取) (结束网络服务数据的读取) (结束网络服务数据的读取) (结束网络服务数据的读取) 相关函数 getservent,getservbyname,getservbyport,setservent 表头文件 #include 定义函数 void endservent(void); 函数说明 endservent()用来关闭由 getservent()所打开的文件。 返回值 范例 参考 getservent()。 4.194.194.194.19 getsockoptgetsockoptgetsockoptgetsockopt(取得 (取得 (取得 (取得 socket socket socket socket 状态) 状态) 状态) 状态) 相关函数 setsockopt 表头文件 #include #include 定义函数 int getsockopt(int s,int level,int optname,void* optval,socklen_t* optlen); 函数说明 getsockopt()会将参数 s所指定的 socket 状态返回。参数 optname 代表欲取得何种选项状态,而参数 optval 则指向欲保存结果的内存地 址,参数 optlen 则为该空间的大小。参数 level、optname 请参考 setsockopt()。 返回值 成功则返回 0,若有错误则返回-1,错误原因存于 errno 错误代码 EBADF 参数 s 并非合法的 socket 处理代码 ENOTSOCK 参数 s为一文件描述词,非 socket ENOPROTOOPT 参数 optname 指定的选项不正确 EFAULT 参数 optval 指针指向无法存取的内存空间 范例 #include #include main() { int s,optval,optlen = sizeof(int); if((s = socket(AF_INET,SOCK_STREAM,0))<0) perror(“socket”); getsockopt(s,SOL_SOCKET,SO_TYPE,&optval,&optlen); printf(“optval = %d\n”,optval); close(s);} 执行 optval = 1 /*SOCK_STREAM 的定义正是此值*/ 4.204.204.204.20 htonlhtonlhtonlhtonl((((将将将将32 32 32 32 位主机字符顺序转换成网络字符顺 位主机字符顺序转换成网络字符顺 位主机字符顺序转换成网络字符顺 位主机字符顺序转换成网络字符顺 序) 序) 序) 序) 相关函数 htons,ntohl,ntohs 表头文件 #include 定义函数 unsigned long int htonl(unsigned long int hostlong); 函数说明 htonl()用来将参数指定的 32 位hostlong 转换成网络字 符顺序。 返回值 返回对应的网络字符顺序。 范例 参考 getservbyport()或connect()。 4.214.214.214.21 htonshtonshtonshtons(将 (将 (将 (将 16 16 16 16 位主机字符顺序转换成网络字符 位主机字符顺序转换成网络字符 位主机字符顺序转换成网络字符 位主机字符顺序转换成网络字符 顺序) 顺序) 顺序) 顺序) 相关函数 htonl,ntohl,ntohs 表头文件 #include 定义函数 unsigned short int htons(unsigned short int hostshort); 函数说明 htons()用来将参数指定的16位 hostshort 转换成网络字符 顺序。 返回值 返回对应的网络字符顺序。 范例 参考 connect()。 4.224.224.224.22 inet_addrinet_addrinet_addrinet_addr(将网络地址转成二进制的数字)(将网络地址转成二进制的数字)(将网络地址转成二进制的数字)(将网络地址转成二进制的数字) 相关函数 inet_aton,inet_ntoa 表头文件 #include #include #include 定义函数 unsigned long int inet_addr(const char *cp); 函数说明 inet_addr()用来将参数 cp 所指的网络地址字符串转换成 网络所使用的二进制数字。网络地址字符串是以数字和点组成的字符串,例 如:“163.13.132.68”。 返回值 成功则返回对应的网络二进制的数字,失败返回-1。 4.234.234.234.23 inet_atoninet_atoninet_atoninet_aton((((将网络地址转成网络二进制的数字将网络地址转成网络二进制的数字将网络地址转成网络二进制的数字将网络地址转成网络二进制的数字)))) 相关函数 inet_addr,inet_ntoa 表头文件 #include #include #include 定义函数 int inet_aton(const char * cp,struct in_addr *inp); 函数说明 inet_aton()用来将参数 cp 所指的网络地址字符串转换成 网络使用的二进制的数字,然后存于参数 inp 所指的 in_addr 结构中。 结构 in_addr 定义如下 struct in_addr { unsigned long int s_addr; }; 返回值 成功则返回非 0值,失败则返回 0。 inet_ntoa(将网络二进制的数字转换成网络地址) 相关函数 inet_addr,inet_aton 表头文件 #include #include #include 定义函数 char * inet_ntoa(struct in_addr in); 函数说明 inet_ntoa()用来将参数 in 所指的网络二进制的数字转换 成网络地址,然后将指向此网络地址字符串的指针返回。 返回值 成功则返回字符串指针,失败则返回 NULL。 不同平台下编写 socket 程序 � Linux 平台下,需要安装 gcc 编译器,用 cc命令编译 c源文件,c源文件需要包含 定义相关系统调用的的头文件,如: � #include � #include � #include � 运行gcc 或cc编译 � gcc -o server server.c gcc -o client client.c
还剩22页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

erikz1990

贡献于2013-05-09

下载需要 5 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf