C+中的套接字对象+; 我试图编写一个基本的套接字程序,它在C++中通过UDP层实现可靠的数据传输。我一直在读beej.us和google,但我仍然对socket对象感到困惑。我来自Python/java后台,从来没有用C++编程过,但是从我理解的,我们的教授给我们完成的程序应该使用某种socket对象,对吗?p>

C+中的套接字对象+; 我试图编写一个基本的套接字程序,它在C++中通过UDP层实现可靠的数据传输。我一直在读beej.us和google,但我仍然对socket对象感到困惑。我来自Python/java后台,从来没有用C++编程过,但是从我理解的,我们的教授给我们完成的程序应该使用某种socket对象,对吗?p>,c++,sockets,C++,Sockets,那么,从我所看到的情况来看,套接字对象似乎既没有getter,也没有setter?调用bind()来修改套接字对象时,它使用什么作为引用? 我看到有一个名为sockfd的int,它似乎在标识每个唯一的套接字,但我看不出简单地调用该数字将如何获取对具有特定sockfd的套接字对象的引用 另外,似乎beej.us和许多youtube教程都使用getaddrinfo()来创建套接字对象,但教授提供的代码中不存在该函数,并且说明表明我们不需要编写任何附加函数 我们必须使用的格式粘贴在下面。有两个文件,一

那么,从我所看到的情况来看,套接字对象似乎既没有getter,也没有setter?调用
bind()
来修改套接字对象时,它使用什么作为引用? 我看到有一个名为sockfd的int,它似乎在标识每个唯一的套接字,但我看不出简单地调用该数字将如何获取对具有特定sockfd的套接字对象的引用

另外,似乎
beej.us
和许多youtube教程都使用
getaddrinfo()
来创建套接字对象,但教授提供的代码中不存在该函数,并且说明表明我们不需要编写任何附加函数

我们必须使用的格式粘贴在下面。有两个文件,一个用于服务器,一个用于客户端。然后是一个包含所有函数的标题

rdt.h:

#ifndef RDT1_H
#define RDT1_H

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netdb.h>


#define PAYLOAD 1000    //size of data payload of the RDT layer

//----- Type defines --------------------------------------------
typedef unsigned char       u8b_t;      // a char
typedef unsigned short      u16b_t;     // 16-bit word
typedef unsigned int        u32b_t;     // 32-bit word 

int rdt_socket();
int rdt_bind(int fd, u16b_t port);
int rdt_target(int fd, char * peer_name, u16b_t peer_port);
int rdt_send(int fd, char * msg, int length);
int rdt_recv(int fd, char * msg, int length);
int rdt_close(int fd);

/* Application process calls this function to create the RDT socket. 
   return   -> the socket descriptor on success, -1 on error
*/
int rdt_socket() {
}

/* Application process calls this function to specify the IP address
   and port number used by itself and assigns them to the RDT socket.
   return   -> 0 on success, -1 on error
*/
int rdt_bind(int fd, u16b_t port){
}

/* Application process calls this function to specify the IP address
   and port number used by remote process and associates them to the 
   RDT socket.
   return   -> 0 on success, -1 on error
*/
int rdt_target(int fd, char * peer_name, u16b_t peer_port){

}

/* Application process calls this function to transmit a message to
   target (rdt_target) remote process through RDT socket.
   msg      -> pointer to the application's send buffer
   length   -> length of application message
   return   -> size of data sent on success, -1 on error
*/
int rdt_send(int fd, char * msg, int length){

}

/* Application process calls this function to wait for a message 
   from the remote process; the caller will be blocked waiting for
   the arrival of the message.
   msg      -> pointer to the receiving buffer
   length   -> length of receiving buffer
   return   -> size of data received on success, -1 on error
*/
int rdt_recv(int fd, char * msg, int length){

}

/* Application process calls this function to close the RDT socket.
*/
int rdt_close(int fd){

}

#endif
#ifndef RDT1#H
#定义RDT1_H
#包括
#包括
#包括
#包括
#包括
#定义有效负载1000//RDT层数据有效负载的大小
//-----类型定义--------------------------------------------
typedef无符号字符u8b\u t;//煤焦
typedef无符号短u16b_t;//16位字
typedef unsigned int u32b_t;//32位字
int rdt_socket();
int-rdt_-bind(int-fd,u16b_-t端口);
int rdt_目标(int fd,字符*对等体_名称,u16b_t对等体_端口);
int rdt_send(int fd,char*msg,int length);
int rdt_recv(int fd,char*msg,int length);
int rdt_关闭(int fd);
/*应用程序进程调用此函数来创建RDT套接字。
return->成功时套接字描述符,-1错误时
*/
int rdt_套接字(){
}
/*应用程序进程调用此函数以指定IP地址
和自身使用的端口号,并将它们分配给RDT套接字。
成功返回->0,错误返回->1
*/
int rdt_绑定(int fd,u16b_t端口){
}
/*应用程序进程调用此函数以指定IP地址
和远程进程使用的端口号,并将它们与
RDT插座。
成功返回->0,错误返回->1
*/
int rdt_目标(int fd,字符*对等体_名称,u16b_t对等体_端口){
}
/*应用程序进程调用此函数将消息传输到
目标(rdt_目标)通过rdt套接字远程进程。
msg->指向应用程序发送缓冲区的指针
长度->应用程序消息的长度
return->成功发送数据的大小,-1错误
*/
int-rdt_发送(int-fd,char*msg,int-length){
}
/*应用程序进程调用此函数以等待消息
来自远程进程;呼叫方将被阻止等待
消息的到达。
msg->指向接收缓冲区的指针
长度->接收缓冲区的长度
return->成功接收数据的大小,-1错误
*/
int-rdt_recv(int-fd,char*msg,int-length){
}
/*应用程序进程调用此函数以关闭RDT套接字。
*/
int rdt_关闭(int fd){
}
#恩迪夫
服务器.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>

#define CPORT 59079
#define SPORT 59080

#define STORAGE "Store"

static float LOSS_RATE=0.0, ERR_RATE=0.0;

/* uncomment this part for part 1 */
#include "rdt-part1.h"
#define MSG_LEN PAYLOAD


/* uncomment this part for part 2 
#include "rdt-part2.h"
#define MSG_LEN PAYLOAD
*/

/* uncomment this part for part 3 
#include "rdt-part3.h"
#define MSG_LEN PAYLOAD*W
*/


int main(int argc, char *argv[]) {

    int sockfd;
    char filepath[200]; 
    char * s;
    char msg[MSG_LEN];
    struct stat sbuf;   
    FILE * testfile;
    int file_len, len;
    int received=0;

    if (argc != 2) {
        printf("Usage: %s 'client hostname'\n", argv[0]);
        exit(0);
    }

    /* update random seed */
    srand(time(NULL));
    /* remove the above line if you want to get the same random 
       sequence for each run - good for testing */

    /* check whether the folder exists */
    if (stat(STORAGE, &sbuf) != 0) {
        printf("Directory ./%s does not exist!!\n", STORAGE);
        printf("Please create the directory %s before start up the server.\n", STORAGE);
        exit(0);
    }

    /* read in packet loss rate and error rate */
    s = getenv("PACKET_LOSS_RATE");
    if (s != NULL) LOSS_RATE = strtof(s, NULL);
    s = getenv("PACKET_ERR_RATE");
    if (s != NULL) ERR_RATE = strtof(s, NULL);
    printf("PACKET_LOSS_RATE = %.2f, PACKET_ERR_RATE = %.2f\n", LOSS_RATE, ERR_RATE);

    // create RDT socket
    sockfd = rdt_socket();

    //specify my own IP address & port number, because if I do not specify, others can not send things to me.
    rdt_bind(sockfd, SPORT);    

    //specify the IP address & port number of my partner 
    rdt_target(sockfd, argv[1], CPORT);

    /* a very simple handshaking protocol */
    // wait for client request
    memset(msg, '\0', MSG_LEN);
    len = rdt_recv(sockfd, msg, MSG_LEN);
    file_len = atoi(msg);
    printf("Received client request: file size = %d\n", file_len);

    memset(msg, '\0', MSG_LEN);
    len = rdt_recv(sockfd, msg, MSG_LEN);
    sprintf(filepath, "%s/%s", STORAGE, msg);
    testfile = fopen(filepath, "w");
    if (!testfile) {
        printf("Cannot open the target file: ./%s for write\n", filepath);

        // send the ERROR response
        memset(msg, '\0', MSG_LEN);
        sprintf(msg, "ERROR");
        rdt_send(sockfd, msg, strlen(msg));
        goto END;
    } else {
        printf("Open file %s for writing successfully\n", filepath);
        // send the ERROR response
        memset(msg, '\0', MSG_LEN);
        sprintf(msg, "OKAY");
        rdt_send(sockfd, msg, strlen(msg));
    }

    /* start the file transfer */   
    printf("Start receiving the file . . .\n");
    // receive the file contents
    while (received < file_len) {
        memset(msg, 0, MSG_LEN);
        len = rdt_recv(sockfd, msg, MSG_LEN);
        fwrite(msg, sizeof(char), len, testfile);
        received += len;
        printf("Received a message of size %d bytes\n", len);
    }

    printf("Complete the file transfer.\n");

END:    
    // close the file
    fclose(testfile);

    // close the rdt socket
    rdt_close(sockfd);

    printf("Server program terminated\n");

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义CPORT 59079
#定义运动59080
#定义存储“存储”
静态浮动损失率=0.0,错误率=0.0;
/*在第1部分中取消对本部分的注释*/
#包括“rdt-part1.h”
#定义MSG_LEN有效负载
/*在第2部分中取消对本部分的注释
#包括“rdt-part2.h”
#定义MSG_LEN有效负载
*/
/*在第3部分中取消对本部分的注释
#包括“rdt-part3.h”
#定义MSG_LEN有效负载*W
*/
int main(int argc,char*argv[]){
int-sockfd;
char文件路径[200];
char*s;
char msg[msg_LEN];
结构统计sbuf;
文件*testfile;
int文件_len,len;
接收到的int=0;
如果(argc!=2){
printf(“用法:%s'客户端主机名'\n',argv[0]);
出口(0);
}
/*更新随机种子*/
srand(时间(空));
/*如果要获得相同的随机值,请删除上面的行
每次运行的顺序-适用于测试*/
/*检查文件夹是否存在*/
如果(统计(存储和sbuf)!=0){
printf(“目录/%s不存在!!\n”,存储);
printf(“请在启动服务器之前创建目录%s。\n”,存储);
出口(0);
}
/*读入数据包丢失率和错误率*/
s=getenv(“数据包丢失率”);
如果(s!=NULL)损失率=strof(s,NULL);
s=getenv(“数据包错误率”);
如果(s!=NULL)错误率=strof(s,NULL);
printf(“数据包丢失率=%.2f,数据包错误率=%.2f\n”,丢失率,错误率);
//创建RDT套接字
sockfd=rdt_socket();
//指定我自己的IP地址和端口号,因为如果我不指定,其他人就不能向我发送东西。
rdt_bind(sockfd,SPORT);
//指定我的合作伙伴的IP地址和端口号
rdt_目标(sockfd,argv[1],CPORT);
/*一个非常简单的握手协议*/
//等待客户端请求
memset(msg,'\0',msg_LEN);
len=rdt_recv(sockfd、msg、msg_len);
文件_len=atoi(msg);
printf(“收到的客户端请求:文件大小=%d\n”,文件长度);
memset(msg,'\0',msg_LEN);
len=rdt_recv(sockfd、msg、msg_len);
sprintf(文件路径,“%s/%s”,存储,消息);
testfile=fopen(文件路径,“w”);
如果(!testfile){
printf(“无法打开目标文件:./%s进行写入”,filepath);
//发送错误响应
memset(msg,'\0',msg_LEN);
sprintf(msg,“错误”);
rdt_发送(sockfd、msg、strlen(msg));
转到终点;
}否则{
printf(“打开文件%s以便成功写入”,filepath);
//发送错误响应
memset(msg,'\0',msg_LEN);
sprintf(msg,“好的”);
研发部
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

#define CPORT 59079
#define SPORT 59080

static float LOSS_RATE=0.0, ERR_RATE=0.0;

/* uncomment this part for part 1 */
#include "rdt-part1.h"
#define MSG_LEN PAYLOAD


/* uncomment this part for part 2 
#include "rdt-part2.h"
#define MSG_LEN PAYLOAD
*/

/* uncomment this part for part 3 
#include "rdt-part3.h"
#define MSG_LEN PAYLOAD*W
*/


int main(int argc, char *argv[]){

    int sockfd;
    FILE * testfile;
    int filelength, len;
    char * fname, * s;
    char msg[MSG_LEN];
    int sent = 0;
    struct timeval starttime, endtime;
    double lapsed;

    if (argc != 3) {
        printf("Usage: %s 'server hostname' 'filename'\n", argv[0]);
        exit(0);
    }   

    /* update random seed */
    srand(time(NULL));
    /* remove the above line if you want to get the same random 
       sequence for each run - good for testing */

    /* read in packet loss rate and error rate */
    s = getenv("PACKET_LOSS_RATE");
    if (s != NULL) LOSS_RATE = strtof(s, NULL);
    s = getenv("PACKET_ERR_RATE");
    if (s != NULL) ERR_RATE = strtof(s, NULL);
    printf("PACKET_LOSS_RATE = %.2f, PACKET_ERR_RATE = %.2f\n", LOSS_RATE, ERR_RATE);

    fname=argv[2];
    //open file
    if (!(testfile = fopen(fname, "r"))) {
        printf("Open file failed.\nProgram terminated.");
        exit(0);
    }
    printf("Open file successfully \n");
    //get the file size
    fseek(testfile, 0L, SEEK_END); 
    filelength = ftell(testfile);   
    printf("File bytes are %d \n",filelength);
    fseek(testfile, 0L, SEEK_SET);

    // create RDT socket
    sockfd = rdt_socket();

    //specify my own IP address & port number, because if I do not specify, others can not send things to me.
    rdt_bind(sockfd, CPORT);     

    //specify the IP address & port number of my partner 
    rdt_target(sockfd, argv[1], SPORT);

    /* a very simple handshaking protocol */ 
    //send the size of the file
    memset(msg, '\0', MSG_LEN);
    sprintf(msg, "%d", filelength);
    rdt_send(sockfd, msg, strlen(msg));  

    //send the file name to server
    rdt_send(sockfd, fname, strlen(fname));

    //wait for server response
    memset(msg, '\0', MSG_LEN);
    len = rdt_recv(sockfd, msg, MSG_LEN);
    if (strcmp(msg, "ERROR") == 0) {
        printf("Server experienced fatal error.\nProgram terminated.\n");
        goto END;
    } else
        printf("Receive server response\n");

    /* start the data transfer */
    printf("Start the file transfer . . .\n");
    gettimeofday(&starttime, NULL);
    // send the file contents
    while (sent < filelength) {
        if ((filelength-sent) < MSG_LEN)
            len = fread(msg, sizeof(char), filelength-sent, testfile);
        else
            len = fread(msg, sizeof(char), MSG_LEN, testfile);
        rdt_send(sockfd, msg, len);
        sent += len;
        usleep(1000);
    }
    gettimeofday(&endtime, NULL);
    printf("Complete the file transfer.\n");
    lapsed = (endtime.tv_sec - starttime.tv_sec)*1.0 + (endtime.tv_usec - starttime.tv_usec)/1000000.0;
    printf("Total elapse time: %.3f s\tThroughtput: %.2f KB/s\n", lapsed, filelength/lapsed/1000.0);

END:    
    // close the file
    fclose(testfile);

    // close the rdt socket
    rdt_close(sockfd);
    printf("Client program terminated\n");

    return 0;
}