线程与网络编程(第六节:通信协议与TCP socket初识)

来源:互联网 发布:网络打印机服务器 编辑:程序博客网 时间:2024/05/29 15:05

1.通信协议
实例:文件传输
A发送一个文件给B
(1)把一个文件分块传送,每块最大1024字节;
(2)数据包格式:前16个字节表示指令
(3)01:开始传送 02:数据包 F1:结束传输
发送方:

#include <stdio.h>#include <string.h>#include "Endian.h"#include "osapi/osapi.h"int main(){    printf("发送方: port=9000 ...\n");    OS_UdpSocket sock;    sock.Open();    // 回车后,开始传送    printf("press enter to send ...");    getchar();    FILE* fp = fopen("123.rar", "rb");    unsigned char buf[1024 + 16];// unsigned char    OS_SockAddr peer("127.0.0.1", 9001); // 对方地址    // 指令:开始传送    buf[0] = 0x01;//01代表开始传输    sock.SendTo(buf, 16, peer);    int count = 0;    while(1)    {               int n = fread(buf + 16, 1, 1024, fp);        if(n <= 0) break;        // 数据包        buf[0] = 0x02;//十六个字节存放状态        sock.SendTo(buf, n + 16, peer);         // 接收应答        int i=sock.RecvFrom(buf, 16, peer);        if (i<0)        {        printf("丢包,请重发!");            getchar();        }        buf[i]=0;        printf("接受结果:%s\n",buf);        printf("send data pcket , count=%d !\n", ++count);    }    // 指令:结束传送    buf[0] = 0xFF;    sock.SendTo(buf, 16, peer);    printf("发送完成,按回车关闭!\n");    getchar();    fclose(fp);    // 关闭socket    sock.Close();    return 0;}接收方:#include <stdio.h>#include <string.h>#include "osapi/osapi.h"/* UDP socket 测试    接收方: 9001*//* 接收文件 */int main(){    printf("接收方: port=9001 ...\n");    OS_SockAddr local("127.0.0.1", 9001);    OS_UdpSocket sock;    sock.Open(local, true);    FILE* fp = fopen("copy.rar", "wb");    unsigned char buf[1024 + 16];    int count = 0;    while(1)    {        OS_SockAddr peer; // 对方的地址        int n = sock.RecvFrom(buf, sizeof(buf), peer);        if(n <= 0)        {            break;        }        // 应答(控制节奏)        sock.SendTo("OK", 2, peer);        if(buf[0] == 0x01)        {            printf("传输开始\n");            continue;        }        else if(buf[0] == 0xFF) // 注意:buf必须为unsigned         {            printf("传输结束\n");            getchar();            break;        }        else        {            fwrite(buf+16, 1, n-16, fp);//buf+16后面是数据            printf("Got: %d bytes \n", n);              //print_bytes(buf, 16);            printf("Packets = %d !\n", ++count);        }    }    fclose(fp);    // 关闭socket    sock.Close();    return 0;}

UDP协议不怕丢包但必须减少丢包
(1)发送方控制节奏,不要太快。
(2)确定应答模式,接收应答后,再发下一个包。
修改:在接受方向向发送方发送指令后,则继续发送。
int i=sock.RecvFrom(buf,16,peer);//发送方
sock.sendTo(“Ok”,16,peer);//接收方
//接收了i个字节
if(i<0){
//代表丢包,重发;
}
buf[i]=0;
……
2.TCP Socket初识
Tcp模式:两端不对等。
TcpSocket的一个应用:用户—总台(主socket)—–服务员(work——socket)。
(1)客户端:

#include <stdio.h>#include  "osapi/osapi.h"int main(){    OS_TcpSocket sock_client;    sock_client.Open();//打开socket    //连接服务器    OS_SockAddr serv_addr("127.0.0.1",9005);    if (sock_client.Connect(serv_addr)<0)    {        printf("无法连接服务器!\n");        return -1;    }    char buf[1024];    //发送请求    strcpy(buf,"Help me!");    int n=strlen(buf);    sock_client.Send(buf,n);    //接收应答    n=sock_client.Recv(buf,sizeof(buf));    buf[n]=0;    printf("Gots:%s\n",buf);    getchar();    //关闭    sock_client.Close();    return 0;}

服务器端:

//工作线程创建#include "TcpConn.h"#include <stdio.h>TcpConn::TcpConn(OS_TcpSocket work_sock){    m_Worksock=work_sock;}TcpConn::~TcpConn(){}int TcpConn::Routine(){    //为client进行服务    char buf[1024];    //接收用户请求    int n=m_Worksock.Recv(buf,1024);    buf[n]=0;    printf("客户请求:%s\n",buf);    //应答客户    strcpy(buf,"yes,ok!");    n=strlen(buf);    m_Worksock.Send(buf,n);    //关闭    m_Worksock.Close();    return 0;}//服务器端:#include <stdio.h>#include "osapi/osapi.h"#include "TcpConn.h"int main(){    OS_TcpSocket sock_serv;    sock_serv.Open(OS_SockAddr(9005),true);    //监听    sock_serv.Listen();    //创建工作线程    while (1)    {        OS_TcpSocket work_sock;        if(sock_serv.Accept(&work_sock) < 0)        {            break;        }//连接验证        TcpConn *conn=new TcpConn(work_sock);        conn->Run();//创建线程;    }    return 0;}

//新建线程进行处理
TcpConn *conn=new TcpConn(work_sock);
conn->Run();//创建线程;
注:(1)客户端连接程序:
if (sock_client.Connect(serv_addr)<0)
{
printf(“无法连接服务器!\n”);
return -1;
}
(2)服务器端验证
if(sock_serv.Accept(&work_sock) < 0)
{
break;
}//连接验证
(3)创建工作线程处理
TcpConn *conn=new TcpConn(work_sock);
conn->Run();

Routine():
主要包括:int n=m_worksock.Recv(buf,1024);
buf[n]=0;
strcpy(buf,”yes,ok!’);
n=strlen(buf);
m_worksock.send(buf,n);

0 0
原创粉丝点击