1、TCP和UDP

TCP是长连接像持续的打电话,UDP是短消息更像是发短信。TCP需要消耗相对较多的资源,但是传输质量有保障,UDP本身是不会考虑传输质量的问题。

2、网络传输内容

我习惯的做法是直接通过TCP传送结构体,当然前提是收发两端都在程序里对目标结构体有充分的定义。特别说明的一点是,要小心收发两端处理器的大小端问题!而且传输信息头里必须包含长度信息,而且通用的是大端。但是,这里的长度和结构体,我选择用小端进行传输。

3、TCPserver实现

参考了别人多线程的回调写法,看起来不错。

tcputil.c(照搬别人的,文件内有作者信息)

  1. /**************************************************
  2. *
  3. * $description: collection of functions
  4. * $author: smstong
  5. * $date: Tue Apr 16 10:24:22 CST 2013
  6. *
  7. * ************************************************/
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <errno.h>
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <netinet/in.h>
  15. #include <pthread.h>
  16. /**************************************************
  17. * func: receive n bytes from socket except an error
  18. * params: fd - socket handle
  19. * buf - memory space to write
  20. * n - size of buf
  21. * return: -1 - error;
  22. * >=0 - actually retceived bytes
  23. *************************************************/
  24. ssize_t recvn(int fd, void* buf, size_t n)
  25. {
  26. char* ptr = (char*)buf; // position pointer
  27. size_t left = n; // bytes left to read
  28. while(left > ) {
  29. size_t nread = read(fd, ptr, left);
  30. if(nread<) {
  31. if(errno==EINTR) { // an error occured
  32. nread = ;
  33. } else {
  34. return -;
  35. }
  36. } else if(nread==) { //normally disconnect, FIN segment received
  37. break;
  38. } else {
  39. left -= nread;
  40. ptr += nread;
  41. }
  42. }
  43. return (n-left);
  44. }
  45.  
  46. /********************************************************
  47. * function: write n bytes to socket except error
  48. * params: fd - socket hanle
  49. * buf - src memory
  50. * n - bytes to write
  51. * return: -1 - error
  52. * >=0 - bytes actually written
  53. * ******************************************************/
  54. ssize_t writen(int fd, void* buf, size_t n)
  55. {
  56. char* ptr = (char*)buf;
  57. size_t left = n;
  58. while(left > ) {
  59. size_t nwrite = write(fd, ptr,left);
  60. if(nwrite<) {
  61. if(errno==EINTR) {
  62. nwrite = ;
  63. } else {
  64. return -;
  65. }
  66. } else if(nwrite==) {
  67. break;
  68. } else {
  69. left -= nwrite;
  70. ptr += nwrite;
  71. }
  72. }
  73. return (n-left);
  74. }
  75.  
  76. static void * thread_f(void *); //thread function
  77. typedef int (*message_handler)(int, void *, uint32_t); // callback function called after received one message
  78.  
  79. /*************************************************************
  80. *
  81. * one thread per connection frameset
  82. *
  83. * ***********************************************************/
  84.  
  85. // thread function's args
  86. struct thread_arg {
  87. int socket;
  88. message_handler msg_handler;
  89. };
  90.  
  91. int start(uint32_t listenip, uint16_t listenport, message_handler handler)
  92. {
  93. int listenfd, connfd;
  94. struct sockaddr_in servaddr;
  95. char buff[];
  96. int n;
  97.  
  98. if( (listenfd = socket(AF_INET, SOCK_STREAM, )) == - ){
  99. printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
  100. exit();
  101. }
  102.  
  103. memset(&servaddr, , sizeof(servaddr));
  104. servaddr.sin_family = AF_INET;
  105. servaddr.sin_addr.s_addr = htonl(listenip);
  106. servaddr.sin_port = htons(listenport);
  107.  
  108. if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -){
  109. printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
  110. return -;
  111. }
  112.  
  113. if( listen(listenfd, ) == -){
  114. printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
  115. return -;
  116. }
  117.  
  118. printf("======waiting for client's request======\n");
  119. while(){
  120. if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -){
  121. printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
  122. continue;
  123. }
  124. /* create a new thread to handle this connection */
  125. pthread_t tid = ;
  126. int rc = ;
  127. struct thread_arg *parg = malloc(sizeof(struct thread_arg));
  128. if(NULL==parg) {
  129. printf("error malloc: %s\n", strerror(errno));
  130. return -;
  131. }
  132. parg->socket = connfd;
  133. parg->msg_handler = handler;
  134. if( != (rc=pthread_create(&tid, NULL, thread_f, parg))) {
  135. printf("%s: %s\n", __func__, strerror(rc));
  136. }
  137. printf(" create thread %u to handle connection %d \n", tid, connfd);
  138. }
  139. close(listenfd);
  140. return ;
  141. }
  142. /***************************
  143. * fun: receive one message
  144. * params: connfd - socket handle
  145. * return: 0 - success;
  146. * -1 - error
  147. *
  148. * **************************/
  149. static int recv_one_message(int connfd, message_handler post_recv_one)
  150. {
  151. uint32_t msg_len = ; /* message length */
  152.  
  153. /* recv length */
  154. if( != recvn(connfd, &msg_len, )) { // something wrong
  155. return -;
  156. }
  157.  
  158. /*很重要的函数,内存*/
  159. //msg_len = ntohl(msg_len);
  160.  
  161. /* recv body */
  162. if(msg_len > 0x7FFFFFFF) {
  163. printf("message body to large%d\n",msg_len);
  164. return -;
  165. }
  166.  
  167. char* buf = malloc(msg_len);/* allocate memory for message body*/
  168. if(NULL == buf) {
  169. printf("%s: malloc failed!\n", __func__);
  170. return -;
  171. }
  172.  
  173. if(msg_len != recvn(connfd, buf, msg_len)) {
  174. free(buf);
  175. return -;
  176. }
  177.  
  178. if(!=post_recv_one(connfd, buf, msg_len)) { // callback
  179. free(buf);
  180. return -;
  181. }
  182.  
  183. free(buf);
  184. return ;
  185. }
  186. /* thread to handle a connection */
  187. static void * thread_f(void * arg)
  188. {
  189. printf(" enter thread %u\n", pthread_self());
  190. struct thread_arg targ = *((struct thread_arg*)arg);
  191. int connfd = targ.socket;
  192. message_handler post_recv_one = targ.msg_handler;
  193. free(arg);
  194.  
  195. int i = ;
  196. while() {
  197. if( != recv_one_message(connfd, post_recv_one)) {
  198. break;
  199. }
  200. printf("%d message : %d\n",connfd,i++);
  201. }
  202. close(connfd);
  203. printf(" leave thread %u\n", pthread_self());
  204. }

tcputil.h

  1. #ifndef TCPUTIL_H
  2. #define TCPUTIL_H
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11.  
  12. //结构体在内存里紧凑排列
  13. #pragma pack(1)
  14. typedef struct { /* raw data */
  15. double tow; // GPS time of the week in second
  16. unsigned char numGps;
  17. unsigned char numBds;
  18. unsigned char numGln;
  19. unsigned char system[MAXSAT]; // system, 0, 1, 2 GPS, BDS & GLN
  20. unsigned char PRN[MAXSAT]; // PRN number
  21. double dDO[MAXSAT]; // Doppler in Hz
  22. double dPR[MAXSAT]; // pseudorange in meter
  23. } diff_t;
  24. #pragma pack()
  25.  
  26. ssize_t writen(int fd, void* buf, size_t n);
  27. ssize_t recvn(int fd, void* buf, size_t n);
  28.  
  29. /*callback function called after received one message, 0-success, -1-error*/
  30. typedef int (*message_handler)(int socket, void * buf, uint32_t size);
  31.  
  32. int start(uint32_t listenip, uint16_t listenport, message_handler handler);
  33.  
  34. #endif

server.c

  1. #include "tcputil.h"
  2.  
  3. diff_t *diff;
  4.  
  5. /* callback called after one message received. */
  6. int msg_handler(int fd, void* buf, uint32_t n)
  7. {
  8. if (!strncmp(buf,"\nrover\n",strlen("\nrover\n")))
  9. {
  10. writen(fd, (char *)diff, sizeof(diff_t));
  11. printf("\t\tsend\n\n");
  12. }
  13. if (!strncmp(buf,"\nstation\n",strlen("\nstation\n")))
  14. {
  15. memcpy((char *)diff, buf+strlen("\nstation\n"), sizeof(diff_t));
  16. printf("\t\tupdate\n\n");
  17. }
  18.  
  19. return ;
  20. }
  21.  
  22. int main(int argc, char** argv)
  23. {
  24. diff=malloc(sizeof(diff_t));
  25. bzero(diff,sizeof(diff_t));
  26. start(,PORT, msg_handler);
  27. free(diff);
  28. }

4、TCPclient实现

略粗糙,将就着看吧

rover.c

  1. #include "tcputil.h"
  2.  
  3. int main(int argc, const char *argv[])
  4. {
  5. diff_t *diff=malloc(sizeof(diff_t));
  6. bzero(diff,sizeof(diff_t));
  7.  
  8. struct sockaddr_in addr;
  9. int sock;
  10.  
  11. if(argc != )
  12. {
  13. fprintf(stderr,"need an IP address\n");
  14. return ;
  15. }
  16. memset(&addr, , sizeof(addr));
  17. addr.sin_family = AF_INET;
  18. inet_aton(argv[],&addr.sin_addr);
  19. addr.sin_port = htons(PORT);
  20. if( (sock = socket(PF_INET, SOCK_STREAM,)) < )
  21. {
  22. perror("socket");
  23. }
  24. if( connect(sock, (struct sockaddr *)&addr, sizeof(addr)) )
  25. {
  26. perror("connect");
  27. }
  28. printf("Connected!\n");
  29. printf("I am rover!\n");
  30. printf("Connected to %s:%d\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
  31.  
  32. char tag[]="\nrover\n";
  33.  
  34. uint32_t len = strlen(tag), msg_len=+strlen(tag);
  35.  
  36. char *msg=malloc(msg_len);
  37. bzero(msg,msg_len);
  38.  
  39. memcpy(msg,&len,);
  40. memcpy(msg+,tag,len);
  41.  
  42. while(){
  43. sleep();
  44. if(write(sock,msg,msg_len) != msg_len)
  45. {
  46. perror("write");
  47. }
  48. read(sock,(char *)diff,sizeof(diff_t));
  49. }
  50.  
  51. free(msg);
  52. close(sock);
  53. return ;
  54. }

station.c

  1. #include "tcputil.h"
  2.  
  3. int main(int argc, const char *argv[])
  4. {
  5. struct sockaddr_in addr;
  6. int sock;
  7.  
  8. diff_t *diff=malloc(sizeof(diff_t));
  9. bzero(diff,sizeof(diff_t));
  10.  
  11. if(argc != )
  12. {
  13. fprintf(stderr,"need an IP address\n");
  14. return ;
  15. }
  16. memset(&addr, , sizeof(addr));
  17. addr.sin_family = AF_INET;
  18. inet_aton(argv[],&addr.sin_addr);
  19. addr.sin_port = htons(PORT);
  20. if( (sock = socket(PF_INET, SOCK_STREAM,)) < )
  21. {
  22. perror("socket");
  23. }
  24. if( connect(sock, (struct sockaddr *)&addr, sizeof(addr)) )
  25. {
  26. perror("connect");
  27. }
  28. printf("Connected!\n");
  29. printf("I am station!\n");
  30. printf("Connected to %s:%d\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
  31.  
  32. char tag[]="\nstation\n";
  33.  
  34. uint32_t len = strlen(tag)+sizeof(diff_t);
  35. int msg_len = +strlen(tag)+sizeof(diff_t);
  36. char *msg=malloc(msg_len);
  37. bzero(msg,msg_len);
  38.  
  39. memcpy(msg,&len,);
  40. memcpy(msg+,tag,strlen(tag));
  41.  
  42. while(){
  43. memcpy(msg++strlen(tag),diff,sizeof(diff_t));
  44. printf("!!!!!!!!!!!!%d\n", msg_len);
  45. if(write(sock,msg,msg_len) != msg_len)
  46. {
  47. perror("write");
  48. }
  49. sleep();
  50. }
  51. free(msg);
  52. close(sock);
  53. return ;
  54. }

附上makefile一枚

  1. all: rover server station
  2.  
  3. rover: rover.c tcputil.o
  4. gcc rover.c tcputil.o -o rover -lpthread
  5.  
  6. server: server.c tcputil.o
  7. gcc server.c tcputil.o -o server -lpthread
  8.  
  9. station:station.c tcputil.o
  10. gcc station.c tcputil.o -o station -lpthread
  11.  
  12. tcputil:tcputil.c
  13. gcc tcputil.c -c -lpthread
  14.  
  15. .PHONY: clean
  16.  
  17. clean:
  18. rm -f *.o rover server station

  

linux网络编程笔记——TCP的更多相关文章

  1. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    [Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...

  2. Linux网络编程笔记(修订版)

    我的网络编程笔记, 因为最近又要做Linux下的网络编程,故重新修订, 其中一些内容参考了文末的链接及文章 1.   基本概念 2.   基本接口 2.1.   打开一个socket 2.2.   将 ...

  3. 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...

  4. Linux网络编程系列-TCP传输控制

    滑动窗口(sliding window) 滑动窗口是用于流量控制的,发送端根据接收端的处理能力发送数据,不至于造成过多的丢包. 是发送方和接收方间的协调,对方的接收窗口大小就是自己的发送窗口大小. 在 ...

  5. linux网络编程系列-TCP/IP模型

    ### OSI:open system interconnection ### 开放系统互联网模型是由ISO国际标准化组织定义的网络分层模型,共七层 1. 物理层:物理定义了所有电子及物理设备的规范, ...

  6. 【Linux 网络编程】TCP/IP四层模型

    应用层.传输层.网络层.链路层 链路层:常用协议 ARP(将物理地址转化为IP地址) RARP(将IP地址转换为物理地址) 网络层(IP层):重要协议ICMP IP IGMP 传输层:重要的协议TCP ...

  7. Linux 网络编程(TCP)

    客户端代码 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/sock ...

  8. Linux网络编程系列-TCP编程实例

    实例: client #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #inc ...

  9. linux网络编程笔记——UDP

    目前这部分代码会出现阻塞问题,暂时尚未解决 #include "udp.h" #include <stdio.h> #include <string.h> ...

随机推荐

  1. 关于spring-mvc的InitBinder注解的参数

    关于spring-mvc的InitBinder注解的参数 通过Spring-mvc的@InitBinder注释的方法可以对WebDataBinder做一些初始化操作.比如设置Validator. 我一 ...

  2. highcharts 结合phantomjs纯后台生成图片系列二之php2

    上篇文章中介绍了phantomjs的使用场景,方法. 本篇文章详细介绍使用php,highcharts 结合phantomjs纯后台生成图片.包含一步步详细的php代码 一.highcharts 结合 ...

  3. windows本地无法启动sqlserver服务

    解决方法:进入服务列表后,选择sqlserver服务,右键然后选择属性,然后在登陆选项卡中,选择本地系统帐户,这样就可以启动sqlserver服务了

  4. Linux下jvm、tomcat、mysql、log4j优化配置

    小菜一直对操作系统心存畏惧,以前也很少接触,这次创业购买了Linux云主机,由于木有人帮忙,只能自己动手优化服务器了.... 小菜的云主机配置大致为:centeos6(32位),4核心cpu,4G内存 ...

  5. jsp获取struts2查询到的数据

    1.在struts2的方法中利用查询语句查询到结果,然后再对结果进行封装,jsp根据封装获取相关信息 struts2的查询和封装方法: private List<FreeMarkerDetail ...

  6. Oracle学习之集合运算

    一.集合运算操作符  UNION:(并集)返回两个集合去掉重复值的所有的记录  UNION ALL:(并集)返回两个集合去掉重复值的所有的记录 INTERSECT:(交集)返回两个集合的所有记录,重复 ...

  7. bzoj3632

    裸的最大团,随机化大法好 多次随机出一个选择顺序然后贪心即可 ..,..] of boolean; a:..] of longint; v:..] of boolean; n,m,i,j,x,y,an ...

  8. UVa 10791 (唯一分解) Minimum Sum LCM

    题意: 输入n,求至少两个正整数,使得这些数的最小公倍数为n且和最小. 分析: 设n的分解式为,很显然单独作为一项,和最小. 这里有两个小技巧: 从2开始不断的除n,直到不能整除为止.这样就省去了素数 ...

  9. 用I/O口模拟IIC总线协议遇到的一些问题

    最近做的一个项目,是基于IIC总线通信的传感器系统.由于另外一个传感器使用的是类IIC协议,而不是标准IIC,所以MCU不能与其通信,最后没有办法,只有通过I/O口模拟的方式实现IIC的总线通信.具体 ...

  10. IOS AFNetworking简介及使用

    转:http://www.it165.net/pro/html/201405/13099.html 一AFNetworking简介AFNetworking是一个在IOS开发中使用非常多网络开源库,适用 ...