- 以前printf信息从串口上打印出来
- 麻烦、不好管理、速率慢
- 引入网络编程,将打印信息通过网络传输到某台机器上观察
- 数据传输三要素:源、目的、长度
- 怎么写程序?
- 文件读写
- 服务器
- send发数据、recv接收数据
Domain,是域的意思 ,分别在数学,计算机学和生物学里有不同的解释和应用。
UDP
- UDP中connect函数并没有实际建立连接链路(UDP也不需要建立链路),只是形式上的获取了目的信息;可以不使用connect函数、利用sendto函数发送数据效果是一样的
网络字节顺序采用big-endian(大端)排序方式;很多嵌入式设备都是采用小端字节序的,需要转换(保险起见,无论设备是大端还是小端,都进行字节序转换,实现与设备无关) unsigned long int htonl(unsigned long int hostlong) unsigned short int htons(unisgned short int hostshort) unsigned long int ntohl(unsigned long int netlong) unsigned short int ntohs(unsigned short int netshort) 在这四个转换函数中,h 代表host, n 代表 network.s 代表short l 代表long
有点小问题
- 客户端中指定连接的是服务器的地址和端口
- 服务端绑定特定端口和地址(一般设为任意地址)
- 客户端的地址信息什么时候填充发送给服务器了? connect中应该填充了
- 机器中的回环地址和实际网卡地址都可以使用
修改电子书源码支持远程打印
int StdoutDebugPrint(const char pccFormat, …) { / 直接把输出信息用printf打印出来即可 */ va_list tArgs; int iNum;
va_start(tArgs, pccFormat);
iNum = vfprintf(stdout, pccFormat, tArgs);
va_end(tArgs);
return iNum;
}
- 看看glibc库中printf的实现
- 所有的库函数都可以在glibc中找到其实现方式
netprint
- NetDbgInit(), NetDbgExit(), NetDbgPrint()
```c
#define PRINT_BUF_SIZE 16*1024
static char * g_pcNetPrintBuf;
static char * g_pcBufTmp;
static int NetDbgInit(void)
{
/* 初始化socket */
...
/* 分配g_pcNetPrintBuf */
g_pcNetPrintBuf = malloc(1024*16);
g_pcBufTmp = malloc(1024);
}
static int NetDbgExit(void)
{
/* 退出socket */
/* 释放内存 */
free(g_pcNetPrintBuf);
free(g_pcBufTmp);
}
/* 将临时缓冲区的数据写入g_pcNetPrintBuf */
static int PutData(char cVal)
{
if(!isFull()){
g_pcNetPrintBuf[g_iWritePos] = cVal;
g_iWritePos = (g_iWritePos+1) % PRINT_BUF_SIZE;
return 0;
}else
return -1;
}
/* 取数据 */
static int GetData(char *pcVal)
{
if(!isEmpty()){
*pcVal = g_pcNetPrintBuf[g_iReadPos];
g_iReadPos = (g_iReadPos+1) % PRINT_BUF_SIZE;
return 0;
}
}
static int NetDbgPrint(const char *pccFormat, ...)
{
/* 把数据放入缓冲区 */
/* 环形缓冲区 */
va_list tArgs;
int iNum;
va_start(tArgs, pccFormat);
iNum = vsfprintf(g_pcBufTmp, pccFormat, tArgs); /* 先把数据打印到临时缓冲区中 */
va_end(tArgs);
for(i=0; i<iNUm; i++){
if(0 != PutData(g_pcBufTmp[i]))
break;
}
/* 如果由客户端连接了,就通过网络把数据发送给客户端 */
/* 可以使用sendto() 或 唤醒线程 */
pthread_mutex_lock(&g_tNetDbgSendMutex);
pthread_cond_signal(&g_tNetDbgSendConVar);
pthread_mutex_unlock(&g_tNetDbgSendMutex);
}
pthread_cond_wait 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程使”条件成立”(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
- 设置打印级别
仿照内核
/* 根据打印级别决定是否打印 */
if ((strTmpBuf[0] == '<') && (strTmpBuf[2] == '>'))
{
dbglevel = strTmpBuf[1] - '0';
if (dbglevel >= 0 && dbglevel <= 9)
{
pcTmp = strTmpBuf + 3;
}
else
{
dbglevel = DEFAULT_DBGLEVEL;
}
}
- 函数定义在使用之前的话,可以不用进行声明
- static类型的函数不应该在头文件中进行声明
telnet服务
- telnetd -l /bin/sh 启动telnet服务
- Telnet协议是TCP/IP协议族中的一员,是Internet远程登录服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力