linux网络编程笔记——TCP
1、TCP和UDP
TCP是长连接像持续的打电话,UDP是短消息更像是发短信。TCP需要消耗相对较多的资源,但是传输质量有保障,UDP本身是不会考虑传输质量的问题。
2、网络传输内容
我习惯的做法是直接通过TCP传送结构体,当然前提是收发两端都在程序里对目标结构体有充分的定义。特别说明的一点是,要小心收发两端处理器的大小端问题!而且传输信息头里必须包含长度信息,而且通用的是大端。但是,这里的长度和结构体,我选择用小端进行传输。
3、TCPserver实现
参考了别人多线程的回调写法,看起来不错。
tcputil.c(照搬别人的,文件内有作者信息)
- /**************************************************
- *
- * $description: collection of functions
- * $author: smstong
- * $date: Tue Apr 16 10:24:22 CST 2013
- *
- * ************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <pthread.h>
- /**************************************************
- * func: receive n bytes from socket except an error
- * params: fd - socket handle
- * buf - memory space to write
- * n - size of buf
- * return: -1 - error;
- * >=0 - actually retceived bytes
- *************************************************/
- ssize_t recvn(int fd, void* buf, size_t n)
- {
- char* ptr = (char*)buf; // position pointer
- size_t left = n; // bytes left to read
- while(left > ) {
- size_t nread = read(fd, ptr, left);
- if(nread<) {
- if(errno==EINTR) { // an error occured
- nread = ;
- } else {
- return -;
- }
- } else if(nread==) { //normally disconnect, FIN segment received
- break;
- } else {
- left -= nread;
- ptr += nread;
- }
- }
- return (n-left);
- }
- /********************************************************
- * function: write n bytes to socket except error
- * params: fd - socket hanle
- * buf - src memory
- * n - bytes to write
- * return: -1 - error
- * >=0 - bytes actually written
- * ******************************************************/
- ssize_t writen(int fd, void* buf, size_t n)
- {
- char* ptr = (char*)buf;
- size_t left = n;
- while(left > ) {
- size_t nwrite = write(fd, ptr,left);
- if(nwrite<) {
- if(errno==EINTR) {
- nwrite = ;
- } else {
- return -;
- }
- } else if(nwrite==) {
- break;
- } else {
- left -= nwrite;
- ptr += nwrite;
- }
- }
- return (n-left);
- }
- static void * thread_f(void *); //thread function
- typedef int (*message_handler)(int, void *, uint32_t); // callback function called after received one message
- /*************************************************************
- *
- * one thread per connection frameset
- *
- * ***********************************************************/
- // thread function's args
- struct thread_arg {
- int socket;
- message_handler msg_handler;
- };
- int start(uint32_t listenip, uint16_t listenport, message_handler handler)
- {
- int listenfd, connfd;
- struct sockaddr_in servaddr;
- char buff[];
- int n;
- if( (listenfd = socket(AF_INET, SOCK_STREAM, )) == - ){
- printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
- exit();
- }
- memset(&servaddr, , sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(listenip);
- servaddr.sin_port = htons(listenport);
- if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -){
- printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
- return -;
- }
- if( listen(listenfd, ) == -){
- printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
- return -;
- }
- printf("======waiting for client's request======\n");
- while(){
- if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -){
- printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
- continue;
- }
- /* create a new thread to handle this connection */
- pthread_t tid = ;
- int rc = ;
- struct thread_arg *parg = malloc(sizeof(struct thread_arg));
- if(NULL==parg) {
- printf("error malloc: %s\n", strerror(errno));
- return -;
- }
- parg->socket = connfd;
- parg->msg_handler = handler;
- if( != (rc=pthread_create(&tid, NULL, thread_f, parg))) {
- printf("%s: %s\n", __func__, strerror(rc));
- }
- printf(" create thread %u to handle connection %d \n", tid, connfd);
- }
- close(listenfd);
- return ;
- }
- /***************************
- * fun: receive one message
- * params: connfd - socket handle
- * return: 0 - success;
- * -1 - error
- *
- * **************************/
- static int recv_one_message(int connfd, message_handler post_recv_one)
- {
- uint32_t msg_len = ; /* message length */
- /* recv length */
- if( != recvn(connfd, &msg_len, )) { // something wrong
- return -;
- }
- /*很重要的函数,内存*/
- //msg_len = ntohl(msg_len);
- /* recv body */
- if(msg_len > 0x7FFFFFFF) {
- printf("message body to large%d\n",msg_len);
- return -;
- }
- char* buf = malloc(msg_len);/* allocate memory for message body*/
- if(NULL == buf) {
- printf("%s: malloc failed!\n", __func__);
- return -;
- }
- if(msg_len != recvn(connfd, buf, msg_len)) {
- free(buf);
- return -;
- }
- if(!=post_recv_one(connfd, buf, msg_len)) { // callback
- free(buf);
- return -;
- }
- free(buf);
- return ;
- }
- /* thread to handle a connection */
- static void * thread_f(void * arg)
- {
- printf(" enter thread %u\n", pthread_self());
- struct thread_arg targ = *((struct thread_arg*)arg);
- int connfd = targ.socket;
- message_handler post_recv_one = targ.msg_handler;
- free(arg);
- int i = ;
- while() {
- if( != recv_one_message(connfd, post_recv_one)) {
- break;
- }
- printf("%d message : %d\n",connfd,i++);
- }
- close(connfd);
- printf(" leave thread %u\n", pthread_self());
- }
tcputil.h
- #ifndef TCPUTIL_H
- #define TCPUTIL_H
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- //结构体在内存里紧凑排列
- #pragma pack(1)
- typedef struct { /* raw data */
- double tow; // GPS time of the week in second
- unsigned char numGps;
- unsigned char numBds;
- unsigned char numGln;
- unsigned char system[MAXSAT]; // system, 0, 1, 2 GPS, BDS & GLN
- unsigned char PRN[MAXSAT]; // PRN number
- double dDO[MAXSAT]; // Doppler in Hz
- double dPR[MAXSAT]; // pseudorange in meter
- } diff_t;
- #pragma pack()
- ssize_t writen(int fd, void* buf, size_t n);
- ssize_t recvn(int fd, void* buf, size_t n);
- /*callback function called after received one message, 0-success, -1-error*/
- typedef int (*message_handler)(int socket, void * buf, uint32_t size);
- int start(uint32_t listenip, uint16_t listenport, message_handler handler);
- #endif
server.c
- #include "tcputil.h"
- diff_t *diff;
- /* callback called after one message received. */
- int msg_handler(int fd, void* buf, uint32_t n)
- {
- if (!strncmp(buf,"\nrover\n",strlen("\nrover\n")))
- {
- writen(fd, (char *)diff, sizeof(diff_t));
- printf("\t\tsend\n\n");
- }
- if (!strncmp(buf,"\nstation\n",strlen("\nstation\n")))
- {
- memcpy((char *)diff, buf+strlen("\nstation\n"), sizeof(diff_t));
- printf("\t\tupdate\n\n");
- }
- return ;
- }
- int main(int argc, char** argv)
- {
- diff=malloc(sizeof(diff_t));
- bzero(diff,sizeof(diff_t));
- start(,PORT, msg_handler);
- free(diff);
- }
4、TCPclient实现
略粗糙,将就着看吧
rover.c
- #include "tcputil.h"
- int main(int argc, const char *argv[])
- {
- diff_t *diff=malloc(sizeof(diff_t));
- bzero(diff,sizeof(diff_t));
- struct sockaddr_in addr;
- int sock;
- if(argc != )
- {
- fprintf(stderr,"need an IP address\n");
- return ;
- }
- memset(&addr, , sizeof(addr));
- addr.sin_family = AF_INET;
- inet_aton(argv[],&addr.sin_addr);
- addr.sin_port = htons(PORT);
- if( (sock = socket(PF_INET, SOCK_STREAM,)) < )
- {
- perror("socket");
- }
- if( connect(sock, (struct sockaddr *)&addr, sizeof(addr)) )
- {
- perror("connect");
- }
- printf("Connected!\n");
- printf("I am rover!\n");
- printf("Connected to %s:%d\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
- char tag[]="\nrover\n";
- uint32_t len = strlen(tag), msg_len=+strlen(tag);
- char *msg=malloc(msg_len);
- bzero(msg,msg_len);
- memcpy(msg,&len,);
- memcpy(msg+,tag,len);
- while(){
- sleep();
- if(write(sock,msg,msg_len) != msg_len)
- {
- perror("write");
- }
- read(sock,(char *)diff,sizeof(diff_t));
- }
- free(msg);
- close(sock);
- return ;
- }
station.c
- #include "tcputil.h"
- int main(int argc, const char *argv[])
- {
- struct sockaddr_in addr;
- int sock;
- diff_t *diff=malloc(sizeof(diff_t));
- bzero(diff,sizeof(diff_t));
- if(argc != )
- {
- fprintf(stderr,"need an IP address\n");
- return ;
- }
- memset(&addr, , sizeof(addr));
- addr.sin_family = AF_INET;
- inet_aton(argv[],&addr.sin_addr);
- addr.sin_port = htons(PORT);
- if( (sock = socket(PF_INET, SOCK_STREAM,)) < )
- {
- perror("socket");
- }
- if( connect(sock, (struct sockaddr *)&addr, sizeof(addr)) )
- {
- perror("connect");
- }
- printf("Connected!\n");
- printf("I am station!\n");
- printf("Connected to %s:%d\n", inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
- char tag[]="\nstation\n";
- uint32_t len = strlen(tag)+sizeof(diff_t);
- int msg_len = +strlen(tag)+sizeof(diff_t);
- char *msg=malloc(msg_len);
- bzero(msg,msg_len);
- memcpy(msg,&len,);
- memcpy(msg+,tag,strlen(tag));
- while(){
- memcpy(msg++strlen(tag),diff,sizeof(diff_t));
- printf("!!!!!!!!!!!!%d\n", msg_len);
- if(write(sock,msg,msg_len) != msg_len)
- {
- perror("write");
- }
- sleep();
- }
- free(msg);
- close(sock);
- return ;
- }
附上makefile一枚
- all: rover server station
- rover: rover.c tcputil.o
- gcc rover.c tcputil.o -o rover -lpthread
- server: server.c tcputil.o
- gcc server.c tcputil.o -o server -lpthread
- station:station.c tcputil.o
- gcc station.c tcputil.o -o station -lpthread
- tcputil:tcputil.c
- gcc tcputil.c -c -lpthread
- .PHONY: clean
- clean:
- rm -f *.o rover server station
linux网络编程笔记——TCP的更多相关文章
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
[Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...
- Linux网络编程笔记(修订版)
我的网络编程笔记, 因为最近又要做Linux下的网络编程,故重新修订, 其中一些内容参考了文末的链接及文章 1. 基本概念 2. 基本接口 2.1. 打开一个socket 2.2. 将 ...
- 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...
- Linux网络编程系列-TCP传输控制
滑动窗口(sliding window) 滑动窗口是用于流量控制的,发送端根据接收端的处理能力发送数据,不至于造成过多的丢包. 是发送方和接收方间的协调,对方的接收窗口大小就是自己的发送窗口大小. 在 ...
- linux网络编程系列-TCP/IP模型
### OSI:open system interconnection ### 开放系统互联网模型是由ISO国际标准化组织定义的网络分层模型,共七层 1. 物理层:物理定义了所有电子及物理设备的规范, ...
- 【Linux 网络编程】TCP/IP四层模型
应用层.传输层.网络层.链路层 链路层:常用协议 ARP(将物理地址转化为IP地址) RARP(将IP地址转换为物理地址) 网络层(IP层):重要协议ICMP IP IGMP 传输层:重要的协议TCP ...
- Linux 网络编程(TCP)
客户端代码 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/sock ...
- Linux网络编程系列-TCP编程实例
实例: client #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #inc ...
- linux网络编程笔记——UDP
目前这部分代码会出现阻塞问题,暂时尚未解决 #include "udp.h" #include <stdio.h> #include <string.h> ...
随机推荐
- 关于spring-mvc的InitBinder注解的参数
关于spring-mvc的InitBinder注解的参数 通过Spring-mvc的@InitBinder注释的方法可以对WebDataBinder做一些初始化操作.比如设置Validator. 我一 ...
- highcharts 结合phantomjs纯后台生成图片系列二之php2
上篇文章中介绍了phantomjs的使用场景,方法. 本篇文章详细介绍使用php,highcharts 结合phantomjs纯后台生成图片.包含一步步详细的php代码 一.highcharts 结合 ...
- windows本地无法启动sqlserver服务
解决方法:进入服务列表后,选择sqlserver服务,右键然后选择属性,然后在登陆选项卡中,选择本地系统帐户,这样就可以启动sqlserver服务了
- Linux下jvm、tomcat、mysql、log4j优化配置
小菜一直对操作系统心存畏惧,以前也很少接触,这次创业购买了Linux云主机,由于木有人帮忙,只能自己动手优化服务器了.... 小菜的云主机配置大致为:centeos6(32位),4核心cpu,4G内存 ...
- jsp获取struts2查询到的数据
1.在struts2的方法中利用查询语句查询到结果,然后再对结果进行封装,jsp根据封装获取相关信息 struts2的查询和封装方法: private List<FreeMarkerDetail ...
- Oracle学习之集合运算
一.集合运算操作符 UNION:(并集)返回两个集合去掉重复值的所有的记录 UNION ALL:(并集)返回两个集合去掉重复值的所有的记录 INTERSECT:(交集)返回两个集合的所有记录,重复 ...
- bzoj3632
裸的最大团,随机化大法好 多次随机出一个选择顺序然后贪心即可 ..,..] of boolean; a:..] of longint; v:..] of boolean; n,m,i,j,x,y,an ...
- UVa 10791 (唯一分解) Minimum Sum LCM
题意: 输入n,求至少两个正整数,使得这些数的最小公倍数为n且和最小. 分析: 设n的分解式为,很显然单独作为一项,和最小. 这里有两个小技巧: 从2开始不断的除n,直到不能整除为止.这样就省去了素数 ...
- 用I/O口模拟IIC总线协议遇到的一些问题
最近做的一个项目,是基于IIC总线通信的传感器系统.由于另外一个传感器使用的是类IIC协议,而不是标准IIC,所以MCU不能与其通信,最后没有办法,只有通过I/O口模拟的方式实现IIC的总线通信.具体 ...
- IOS AFNetworking简介及使用
转:http://www.it165.net/pro/html/201405/13099.html 一AFNetworking简介AFNetworking是一个在IOS开发中使用非常多网络开源库,适用 ...