转自:http://blog.csdn.net/liujia2100/article/details/9006479

版权声明:本文为博主原创文章,未经博主允许不得转载。

  1. 各个主要函数的功能:
  2.  
  3. socket
  4.  
  5. int socket(int domain, int type,int protocol)
  6.  
  7. domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX AF_INET 等).
  8. AF_UNIX 只能够用于单一的 Unix 系统进程间通信,而 AF_INET 是针对 Internet 的,因而可以允
  9. 许在远程 主机之间通信(当我们 man socket 时发现 domain 可选项是 PF_*而不是 AF_*,因
  10. glibc posix 的实现 所以用 PF 代替了 AF,不过我们都可以使用的).
  11.  
  12. type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM 等) SOCK_STREAM
  13. 表明我们用的是 TCP 协议,这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM
  14. 表明我们用的是 UDP 协议,这样只会提供定长的,不可靠,无连接的通信.
  15.  
  16. protocol:由于我们指定了 type,所以这个地方我们一般只要用 来代替就可以了
  17. socket 为网络通讯做基本的准备.成功时返回文件描述符,失败时返回-,看 errno 可知道出错
  18. 的详细情况.
  19.  
  20. bind
  21. int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
  22.  
  23. sockfd:是由 socket 调用返回的文件描述符.
  24.  
  25. addrlen:是 sockaddr 结构的长度.
  26.  
  27. my_addr:是一个指向 sockaddr 的指针. 在中有 sockaddr 的定义
  28.  
  29. struct sockaddr{
  30. unisgned short as_family;
  31. char sa_data[];
  32. };
  33.  
  34. 不过由于系统的兼容性, 我们一般不用这个头文件, 而使用另外一个结构(struct sockaddr_in) 来代替.在中有 sockaddr_in 的定义
  35. struct sockaddr_in{
  36. unsigned short sin_family;
  37. unsigned short int sin_port;
  38. struct in_addr sin_addr;
  39. unsigned char sin_zero[];
  40.  
  41. 我们主要使用 Internet 所以 sin_family 一般为 AF_INET,sin_addr 设置为 INADDR_ANY
  42. 表示可以和任何的主机通信,sin_port 是我们要监听的端口号.sin_zero[]是用来填充的. bind
  43. 将本地的端口同 socket 返回的文件描述符捆绑在一起.成功是返回 ,失败的情况和 socket
  44.  
  45. listen
  46.  
  47. int listen(int sockfd,int backlog)
  48.  
  49. sockfd:是 bind 后的文件描述符.
  50.  
  51. backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时, 使用这个表示
  52. 可以介绍的排队长度. listen 函数将 bind 的文件描述符变为监听套接字.返回的情况和 bind
  53. 样.
  54.  
  55. accept
  56. int accept(int sockfd, struct sockaddr *addr,int *addrlen)
  57.  
  58. sockfd:是 listen 后的文件描述符.
  59.  
  60. addr,addrlen 是用来给客户端的程序填写的,服务器端只要传递指针就可以了. bind,listen
  61. accept 是服务器端用的函数,accept 调用时,服务器端的程序会一直阻塞到有一个客户程序
  62. 发出了连接. accept 成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描
  63. 述符写信息了. 失败时返回-
  64.  
  65. connect
  66. int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)
  67. sockfd:socket 返回的文件描述符.
  68.  
  69. serv_addr:储存了服务器端的连接信息.其中 sin_add 是服务端的地址
  70.  
  71. addrlen:serv_addr 的长度
  72.  
  73. connect 函数是客户端用来同服务端连接的.成功时返回 ,sockfd 是同服务端通讯的文件
  74. 描述符 失败时返回-.
  75.  
  76.  
  77. gethostbyname gethostbyaddr 都涉及到一个 hostent 的结构体,如下所示:
  78.  
  79. Struct hostent{
  80. char *h_name;/*正式主机名*/
  81. char **h_aliases;/*主机别名*/
  82. int h_addrtype;/*地址类型*/
  83. int h_length;/*地址长度*/
  84. char **h_addr_list;/*指向 IPv4或 IPv6的地址指针数组*/
  85. }
  86. 所需头文件 #include <netdb.h>
  87.  
  88. 函数原型 Struct hostent *gethostbyname(const char *hostname)
  89.  
  90. 函数传入值 Hostname:主机名
  91.  
  92. 函数返回值
  93.  
  94. 成功:
  95. hostent 类型指针
  96.  
  97. 出错:−
  98.  
  99. 服务端源码:
  100. [cpp] view plain copy
  101.  
  102. #include <stdio.h>
  103. #include <stdlib.h>
  104. #include <errno.h>
  105. #include <sys/types.h>
  106. #include <sys/time.h>
  107. #include <unistd.h>
  108. #include <string.h>
  109. #include <netdb.h>
  110. #include <sys/types.h>
  111. #include <netinet/in.h>
  112. #include <sys/socket.h>
  113.  
  114. int main(int argc, char *argv[])
  115. {
  116. int sockfd,new_fd;
  117. int sockaddr_size;
  118. int ret;
  119. int len;
  120. struct sockaddr_in server_addr; //结构体sockaddr_in 和 aockaddr 是兼容的
  121. struct sockaddr_in client_addr;
  122. int sin_size,portnumber;
  123. char buf[];
  124.  
  125. fd_set rfds;
  126. struct timeval tv;
  127. int maxfd;
  128. FD_ZERO(&rfds);
  129. FD_SET(STDIN_FILENO, &rfds);
  130.  
  131. if((portnumber = atoi(argv[]))<)
  132. {
  133. printf("port number error, will exit\n");
  134. exit();
  135. }
  136. /* 服务器端开始建立 socket 描述符 */
  137. if((sockfd=socket(AF_INET,SOCK_STREAM,))==-) //AF_INET也可以用PF_INET代替,表明针对錓neternet,可以建立远程连接。SOCK_STREAM表明使用的是TCP协议
  138. { //而 SOCK_DGRAM 表明我们用的是 UDP 协议
  139. printf("socket, will exit\n");
  140. close(sockfd);
  141. exit();
  142. }
  143. /* 服务器端填充 sockaddr 结构 */
  144. bzero(&server_addr,sizeof(struct sockaddr_in));
  145. server_addr.sin_family=AF_INET;
  146. server_addr.sin_addr.s_addr=htonl(INADDR_ANY); //标识可以和任何主机通信
  147. server_addr.sin_port=htons(portnumber);
  148.  
  149. /* 捆绑 sockfd 描述符 */
  150. if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-)
  151. {
  152. printf("bind error, will exit\n");
  153. close(sockfd);
  154. exit();
  155. }
  156. /* 监听 sockfd 描述符 */
  157. if(listen(sockfd,)==-) //设置客户端请求排队的最大长度,允许最大5个
  158. {
  159. printf("listen, will exit\n");
  160. close(sockfd);
  161. exit();
  162. }
  163.  
  164. while()
  165. {
  166. /* 服务器阻塞,直到客户程序建立连接 */
  167. printf("Will go to talk, wait connecting...\n");
  168. sockaddr_size = sizeof(struct sockaddr);
  169. //int accept(int sockfd, struct sockaddr *addr,int *addrlen)
  170. if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sockaddr_size))==-)
  171. {
  172. printf("accept error, will exit\n");
  173. close(sockfd);
  174. exit();
  175. }
  176. else
  177. {
  178. printf("server: get connection from %s, port %d, socket %d\n",
  179. (char *)inet_ntoa(client_addr.sin_addr),
  180. ntohs(client_addr.sin_port),
  181. new_fd);
  182. }
  183. //进行会话
  184. while()
  185. {
  186.  
  187. FD_ZERO(&rfds);
  188. FD_SET(STDIN_FILENO, &rfds);
  189. FD_SET(new_fd, &rfds);
  190. //maxfd = new_fd > STDIN_FILENO ? newfd :STDIN_FILENO;
  191. //maxfd = maxfd + 1;
  192. maxfd = new_fd + ;
  193.  
  194. tv.tv_sec = ;
  195. tv.tv_usec = ;//设置等待时间
  196. ret = select(maxfd, &rfds, NULL, NULL, &tv);
  197. if(ret<)
  198. {
  199. printf("select error, process will eixt\n");
  200. exit();
  201. }
  202. else if(FD_ISSET(STDIN_FILENO, &rfds))//测试是否有数据
  203. {
  204. bzero(buf,);
  205. //printf("Server :");
  206. fgets(buf, , stdin);
  207. if (!strncasecmp(buf, "quit", ))
  208. {
  209. printf("current talk exit\n");
  210. FD_CLR(new_fd, &rfds);
  211. close(new_fd);
  212. break;
  213. }
  214. //printf("Server :%s\n",buf);
  215. // int recv(int sockfd,void *buf,int len,int flags)
  216. // int send(int sockfd,void *buf,int len,int flags)
  217. //最后一个参数可以是0,也可以是
  218. /* _______________________________________________________________
  219. | MSG_DONTROUTE | 不查找路由表 |
  220. | MSG_OOB | 接受或者发送带外数据 |
  221. | MSG_PEEK | 查看数据,并不从系统缓冲区移走数据 |
  222. | MSG_WAITALL | 等待所有数据 |
  223. |--------------------------------------------------------------|
  224. */
  225. len = send(new_fd,buf,strlen(buf)-,);
  226. if(len < )
  227. {
  228. printf("send fail\n");
  229. }
  230.  
  231. }
  232. else if(FD_ISSET(new_fd, &rfds))
  233. {
  234.  
  235. bzero(buf,);
  236. len = recv(new_fd,buf,strlen(buf)-,);
  237. if(len < )
  238. {
  239. printf("receive fail\n");
  240. }
  241. if(len == )//当客户端终止运行的时候,会不断检测到sockfd的状态变化,但是收到的信息长度为0
  242. {
  243. printf("Client has already exit, will exit\n");
  244. FD_CLR(new_fd, &rfds);
  245. close(new_fd);
  246. break;
  247.  
  248. }
  249. if (!strncasecmp(buf, "quit", ))
  250. {
  251. printf("current talk exit\n");
  252. FD_CLR(new_fd, &rfds);
  253. close(new_fd);
  254. break;
  255. }
  256. buf[len+]='\0';
  257. printf(" Client :%s\n",buf);
  258.  
  259. }
  260.  
  261. }
  262.  
  263. }
  264.  
  265. }
  266.  
  267. 客户端:
  268. [cpp] view plain copy
  269.  
  270. #include <stdio.h>
  271. #include <stdlib.h>
  272. #include <errno.h>
  273. #include <sys/types.h>
  274. #include <sys/time.h>
  275. #include <unistd.h>
  276. #include <string.h>
  277. #include <netdb.h>
  278. #include <sys/types.h>
  279. #include <netinet/in.h>
  280. #include <sys/socket.h>
  281.  
  282. int main(int argc, char *argv[])
  283. {
  284. int sockfd,new_fd;
  285. int sockaddr_size;
  286. int ret;
  287. int len;
  288. struct sockaddr_in server_addr; //结构体sockaddr_in 和 aockaddr 是兼容的
  289. struct hostent *host;
  290. int sin_size,portnumber;
  291. char buf[];
  292.  
  293. fd_set rfds;
  294. struct timeval tv;
  295. int maxfd;
  296. FD_ZERO(&rfds);
  297. FD_SET(STDIN_FILENO, &rfds);
  298.  
  299. if((host=gethostbyname(argv[])) == )
  300. {
  301. printf("server ip %s error\n",argv[]);
  302. exit();
  303. }
  304.  
  305. if((portnumber = atoi(argv[]))<)
  306. {
  307. printf("port number error, will exit\n");
  308. exit();
  309. }
  310. /* 客户程序开始建立 sockfd 描述符 */
  311. if((sockfd=socket(AF_INET,SOCK_STREAM,))==-) //AF_INET也可以用PF_INET代替,表明针对錓neternet,可以建立远程连接。SOCK_STREAM表明使用的是TCP协议
  312. { //而 SOCK_DGRAM 表明我们用的是 UDP 协议
  313. printf("socket, will exit\n");
  314. exit();
  315. }
  316. /* 客户程序填充服务端的资料 */
  317. bzero(&server_addr,sizeof(struct sockaddr_in));
  318. server_addr.sin_family=AF_INET;
  319. server_addr.sin_port=htons(portnumber);
  320. server_addr.sin_addr=*((struct in_addr *)host->h_addr);
  321.  
  322. /* 客户程序发起连接请求 */
  323. if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-)
  324. {
  325. printf("connect will exit\n");
  326. exit();
  327. }
  328. printf("start talk...\n");
  329.  
  330. FD_SET(sockfd, &rfds);
  331. //进行会话
  332. while()
  333. {
  334.  
  335. FD_ZERO(&rfds);
  336. FD_SET(STDIN_FILENO, &rfds);
  337. FD_SET(sockfd, &rfds);
  338.  
  339. //maxfd = new_fd > STDIN_FILENO ? newfd :STDIN_FILENO;
  340. //maxfd = maxfd + 1;
  341. maxfd = sockfd + ;
  342.  
  343. tv.tv_sec = ;
  344. tv.tv_usec = ;//设置等待时间
  345. ret = select(maxfd, &rfds, NULL, NULL, &tv);
  346. if(ret<)
  347. {
  348. printf("select error, process will eixt\n");
  349. exit();
  350. }
  351. else if(FD_ISSET(STDIN_FILENO, &rfds))//测试是否有数据
  352. {
  353. bzero(buf,);
  354. //printf("Client :");
  355. fgets(buf, , stdin);
  356. if (!strncasecmp(buf, "quit", ))
  357. {
  358. printf("current talk exit\n");
  359. FD_CLR(sockfd, &rfds);
  360. close(sockfd);
  361. break;
  362. }
  363. //printf("Client :%s\n",buf);
  364. // int recv(int sockfd,void *buf,int len,int flags)
  365. // int send(int sockfd,void *buf,int len,int flags)
  366. //最后一个参数可以是0,也可以是
  367. /* _______________________________________________________________
  368. | MSG_DONTROUTE | 不查找路由表 |
  369. | MSG_OOB | 接受或者发送带外数据 |
  370. | MSG_PEEK | 查看数据,并不从系统缓冲区移走数据 |
  371. | MSG_WAITALL | 等待所有数据 |
  372. |--------------------------------------------------------------|
  373. */
  374. len = send(sockfd,buf,strlen(buf)-,);
  375. if(len < )
  376. {
  377. printf("send fail\n");
  378. }
  379.  
  380. }
  381. else if(FD_ISSET(sockfd, &rfds))
  382. {
  383.  
  384. bzero(buf,);
  385. len = recv(sockfd,buf,strlen(buf)-,);
  386. if(len < )
  387. {
  388. printf("receive fail\n");
  389. }
  390. if(len == )//当服务器终止运行的时候,会不断检测到sockfd的状态变化,但是收到的信息长度为0
  391. {
  392. printf("Server has already exit, will exit\n");
  393. FD_CLR(sockfd, &rfds);
  394. close(sockfd);
  395. break;
  396.  
  397. }
  398. if (!strncasecmp(buf, "quit", ))
  399. {
  400. printf("current talk exit\n");
  401. FD_CLR(sockfd, &rfds);
  402. close(sockfd);
  403. break;
  404. }
  405. buf[len+]='\0';
  406. printf(" Server: %s\n",buf);
  407.  
  408. }
  409.  
  410. }
  411.  
  412. }

socket 编程 TCP 实现简单聊天功能【转】的更多相关文章

  1. 使用socket编程实现一个简单的文件服务器

    使用socket编程实现一个简单的文件服务器.客户端程序实现put功能(将一个文件从本地传到文件服务器)和get功能(从文件服务器取一远程文件存为本地文件).客户端和文件服务器不在同一台机器上. pu ...

  2. Win Socket编程原理及简单实例

    [转]http://www.cnblogs.com/tornadomeet/archive/2012/04/11/2442140.html 使用Linux Socket做了小型的分布式,如Linux ...

  3. 利用socket.io+nodejs打造简单聊天室

    代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...

  4. C#版 Socket编程(最简单的Socket通信功能)

    示例程序是同步套接字程序,功能很简单,只是客户端发给服务器一条信息,服务器向客户端返回一条信息:这里只是一个简单的示例,是一个最基本的socket编程流程,在接下来的文章中,会依次记录套接字的同步和异 ...

  5. python socket编程实现的简单tcp迭代server

    与c/c++ socket编程对照见http://blog.csdn.net/aspnet_lyc/article/details/38946915 server: import socket POR ...

  6. Linux C Socket编程原理及简单实例

    部分转自:http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx 1.   什么是TCP/IP.UDP? 2.   Socket在哪里 ...

  7. java基础之Socket编程概述以及简单案例

    概述: 用来实现网络互连的 不同的计算机上 运行的程序间 可以进行数据交互  也就是用来在不同的电脑间, 进行数据传输. 三大要素: IP地址: 设备(电脑,手机,ipad)在网络中的唯一标识. 组成 ...

  8. Socket编程 Tcp和粘包

    大多数程序员都要接触网络编程,Web开发天天和http打交道.稍微底层一点的程序员,就是TCP/UDP . 对程序员来说,Tcp/udp的核心是Socket编程. 我的浅薄的观点---------理解 ...

  9. 3、linux下Socket编程-TCP/UDP

    1.什么是Socket 网络的 Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符.Socket也具有一个类似于打开文件的函数调用Socket(),该函数返 回一个整型的Socke ...

随机推荐

  1. TCP标志位简析

    TCP标志位简析   TCP标志位  URG:此标志表示TCP包的紧急指针域(后面马上就要说到)有效,用来保证TCP连接不被中断,并且督促中间层设备要尽快处理这些数据: ACK:此标志表示应答域有效, ...

  2. E2202 Required package 'rtl' not found"

    最近重新下载了一个delphi Berlin 10.1.2绿色版本,解压后剪切到别的盘上了,一些需要直接编译的.dpk包,例如fastReport都不能了,都提示E2202 Required pack ...

  3. OBJ文件

    OBJ文件是Alias|Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种标准3D模型文件格式,很适合用于3D软件模 ...

  4. JavaScript中:表达式和语句的区别

    JavaScript中:表达式和语句的区别 Javascript语言精粹:表达式是由运算符构成,并运算产生结果的语法结构.程序是由语句构成,语句则是由“:(分号)”分隔的句子或命令.如果在表达式后面加 ...

  5. Hyperledger Fabric 实战(十): Fabric node SDK 样例 - 投票DAPP

    Fabric node SDK 样例 - 投票DAPP 参考 fabric-samples 下的 fabcar 加以实现 目录结构 . ├── app │ ├── controllers │ │ └─ ...

  6. 【QQ】前端实现QQ会话功能

    <a href="tencent://message/?uin=客服QQ号码&Menu=yes" target="blank"></a ...

  7. 洛谷 P3527 [POI2011]MET-Meteors 解题报告

    P3527 [POI2011]MET-Meteors 题意翻译 \(\tt{Byteotian \ Interstellar \ Union}\)有\(N\)个成员国.现在它发现了一颗新的星球,这颗星 ...

  8. 洛谷 P1363 幻想迷宫 解题报告

    P1363 幻想迷宫 题目描述 背景 Background (喵星人LHX和WD同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫.) WD:呜呜,肿么办啊-- LHX:mo ...

  9. 【简单算法】22.删除链表的倒数第N个节点

    题目: 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: ->->->->, 和 n = . 当删除了倒数第二个节点后,链表变为 -& ...

  10. C++虚基类的初始化

    #include<iostream> using namespace std; class Base{ public: Base(int sa) { a=sa; cout<<& ...