网络编程 pthread/fork

一、查看while代码

查看、理解。注意是否满足自注释。

1.client.c

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQXVnZW5zdGVybsK3S1VO,size_20,color_FFFFFF,t_70,g_se,x_16

 

2.server-while-tcp.c

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQXVnZW5zdGVybsK3S1VO,size_20,color_FFFFFF,t_70,g_se,x_16

 

二、编译并在ubuntu上运行

1.client.c

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQXVnZW5zdGVybsK3S1VO,size_17,color_FFFFFF,t_70,g_se,x_16

 

2.server-while-tcp.c

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQXVnZW5zdGVybsK3S1VO,size_17,color_FFFFFF,t_70,g_se,x_16

 

三、修改服务器为多线程模式

2.client.c

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <netdb.h>

#include <unistd.h>

#include <stdlib.h>

#include <arpa/inet.h>//TODO: 某些头文件

#define MAX_BUFFER 1024

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

    int local_socket;

    int return_code;

    char send_and_receive_buffer[MAX_BUFFER];

    int port_number;

    int nr_bytes_read;

 static struct sockaddr_in server_sockaddr;

 //客户端运行需要给出具体的连接地址和端口 

    if (argc != 3) {

        printf("Usage: %s server_ip_address port_number \n", argv[0]);

        return 1;

    }

    //获得输入的端口

    port_number = atoi(argv[2]);

 

    //创建套节字用于客户端的连接

    local_socket = socket(PF_INET, SOCK_STREAM, 0);//TODO: 调用socket

    if (local_socket < 0) {//TODO: 如果错误

        perror("ERR socket.");

        return 1;

    }

 

    //填充关于服务器的套节字信息

    memset(&server_sockaddr, 0, sizeof(server_sockaddr));

    server_sockaddr.sin_family = AF_INET;

    server_sockaddr.sin_addr.s_addr = inet_addr(argv[1]);

    server_sockaddr.sin_port = htons(port_number);

 

    //连接指定的服务器 

    return_code = (local_socket,(struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr));//TODO: 调用connect

    if (return_code == -1) {//TODO: 如果错误

        perror("ERR connect.");

        close(local_socket);

        return 1;

    }

 

    memset(send_and_receive_buffer, 0, MAX_BUFFER);

    //用户输入信息后,程序将输入的信息通过套接字发送给服务器 ,然后调用read函数从服务器中读取发送来的信息。

    //输入“#”退出 

    while (1) {

        //TODO: 12345 改为自己的学号,此处不要修改write调用和STDOUT_FILENO参数!

        write(STDOUT_FILENO, "Type in a string for 201930310050:", strlen("Type in a string for 201930310050:"));

        nr_bytes_read = read(STDOUT_FILENO, send_and_receive_buffer, MAX_BUFFER);//TODO: 调用read, 从STDIN_FILENO读

        if (nr_bytes_read > 0)

            write(local_socket, send_and_receive_buffer, nr_bytes_read);//TODO: 调用write,写socket

        nr_bytes_read = read(local_socket, send_and_receive_buffer, nr_bytes_read);//TODO: 调用read,读socket

        if (nr_bytes_read > 0)

            printf("Message form server: %s\n", send_and_receive_buffer);

        if (send_and_receive_buffer[0] == '#')

            break;

        //提示:刚才几句忽略了某些可能的错误,你能加上么?

    }

    close(local_socket);

    return 0;

}

2.server-while-tcp.c

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <netdb.h>

#include <unistd.h>

#include <errno.h>

#include <signal.h>

#include <sys/wait.h>

#include <pthread.h>

#include <ctype.h>

#include <stdlib.h>//TODO: 某些头文件

#define MAX_BUFFER 1024

 

void* thread_function(void* arg_array) {

    int nr_bytes_read, char_index;

    char receive_and_send_buffer[MAX_BUFFER];

    int* p_arg = (int*)arg_array;

    int thread_session_socket = *p_arg;

    printf("thread_session_socket = %d\n", thread_session_socket);

    while (1) {

        nr_bytes_read = read(thread_session_socket, receive_and_send_buffer, MAX_BUFFER);//TODO: 尝试从socket读取

        if (receive_and_send_buffer[0] == '#')//TODO: 如果错误,或没能从socket读取字符

            break;

        printf("Message from client(%d): %s\n", nr_bytes_read, receive_and_send_buffer);

        for (char_index = 0; char_index < nr_bytes_read; char_index++)

            receive_and_send_buffer[char_index] = toupper(receive_and_send_buffer[char_index]);//TODO: 转换为大写

        write(thread_session_socket, receive_and_send_buffer, char_index);//TODO: 返回给客户端

    }

    close(thread_session_socket);//TODO: 关闭socket

    return 0;

}

 

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

    socklen_t size_of_client_sockaddr;

    pthread_t tid;

    int listen_socket;

    int session_socket;

    int return_code;

    int port_number;

 

    struct sockaddr_in client_remote_sockaddr;

    struct sockaddr_in server_local_sockaddr;

 

    //服务器端运行时要给出端口信息,该端口为监听端口 

    if (argc != 2) {

        printf("Usage:%s port_number \n", argv[0]);

        return 1;

    }

 

    //获得输入的端口 

    port_number = atoi(argv[1]);

 

    //创建套接字用于服务器的监听 

    listen_socket = (PF_INET, SOCK_STREAM, 0);//TODO: socket()

    if (listen_socket < 0) {//TODO: 如果出错

        perror("ERR socket.");

        return 1;

    }

 

    //填充关于服务器的套节字信息

    memset(&server_local_sockaddr, 0, sizeof(server_local_sockaddr));

    server_local_sockaddr.sin_family = AF_INET;

    server_local_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    server_local_sockaddr.sin_port = htons(port_number);

 

    //将服务器和套节字绑定

    return_code = bind(listen_socket, (struct sockaddr *)&server_local_sockaddr, sizeof(server_local_sockaddr));//TODO: 调用bind绑定地址和端口(提供服务的位置)

    if (return_code == -1) {//TODO: 如果出错

        perror("ERR bind.");

        close(listen_socket);//TODO: 关闭监听socket

        return 1;

    }

 

    //监听指定端口,连接5个客户端 

    return_code = (listen_socket, 5);//TODO: 请求监听、提供服务

    if (return_code == -1) {//TODO: 如果出错

        perror("ERR listen.");

        close(listen_socket);//TODO: 关闭监听socket

        return 1;

    }

 

    //对每个连接来的客户端创建一个线程,单独与其进行通信。

    //首先调用read函数读取客户端发送来的信息,将其转换成大写后发送回客户端,#退出。

    while (1) {

        size_of_client_sockaddr = sizeof(client_remote_sockaddr);

        //TODO: 12345 改为自己的学号,此处不要修改write调用和STDOUT_FILENO参数!

        write(STDOUT_FILENO, "Listening & Accepting for 201930310050 ...\n", strlen("Listening & Accepting for 201930310050 ...\n"));

        return_code = accept(listen_socket, (struct sockaddr *)&client_remote_sockaddr, &size_of_client_sockaddr);//TODO: 调用accept阻塞,接到客户机时返回 session_socket

        if (return_code < 0) {//TODO: 如果出错

            if (errno == EINTR) continue;

            else {

                perror("ERR accept(): cannot accept client connect request");

                close(listen_socket);//TODO: 关闭socket

                return 1;

            }

        }

        printf("session_socket = %d\n", session_socket); //打印建立连接的客户端产生的套节字

        return_code = pthread_create(&tid, NULL, thread_function, &session_socket);//TODO: 调用 pthread_create,将 session_socket传递给 thread_function

        if (return_code == -1) {//TODO: 如果出错

            perror("ERR pthread_create()");

            close(listen_socket);//TODO: 关闭一个socket

            close(session_socket);//TODO: 关闭另一个socket

            return 1;

        }

    }

    return 0;

}

四、提高项

1.使用gcc编译程序

gcc client.c -o 1

gcc server-pthread-tcp.c -o 2 -lpthread

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQXVnZW5zdGVybsK3S1VO,size_17,color_FFFFFF,t_70,g_se,x_16

 遇到问题:使用以下命令运行会报错。

gcc server-pthread-tcp.c -o 2

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQXVnZW5zdGVybsK3S1VO,size_16,color_FFFFFF,t_70,g_se,x_16

 解决方法:结尾加上“-lpthread”,链接“pthread_create”库。

五、git命令行操作push、log截图

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQXVnZW5zdGVybsK3S1VO,size_18,color_FFFFFF,t_70,g_se,x_16

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值