具有<socket.h>的C客户端服务器

时间:2018-08-22 20:44:33

标签: c sockets tcp server client

你好,晚上好

我正在用C编写一个客户端和服务器对程序。现在,我使它们同时运行,并通过路由器设置提供对服务器端口的访问,我可以建立本地和全局连接以进行准系统聊天和向前。到目前为止,这两个程序都是这样做的。

客户:

  • 创建套接字

  • 创建一个sockaddr_in(端口和IP地址)

  • 使用sockaddr_in将套接字连接到服务器

  • 进入循环以一次读取/写入服务器

服务器:

  • 创建套接字

  • 创建一个sockaddr_in(端口和IP地址)

  • 将套接字绑定到sockaddr_in

  • 在套接字上监听请求

  • 接受请求

  • 进入循环以一次读取/写入服务器

我的问题:

要正确处理和错误处理这些单个步骤,我需要考虑什么?

到目前为止,我得到的是这样的代码:

printf("trying to connect to: IPv4 <%s> port <%s> ...", argv[1], argv[2]);

if(connect(net_socket, (struct sockaddr *)&server_address, sizeof server_address) == -1)
{
    fprintf(stderr, "\ntcp connection failed.\n");
    exit(4);
}

printf(" success.\nconnection to server: IPv4 <%s> port <%s>\n", argv[1], argv[2]);

这样的代码包装了这些程序从套接字创建到连接和接受的所有步骤。在正确的输入下,他们就可以工作。

我想扩展程序:

  • 双方同时读写

  • 多个客户端到服务器,而不是客户端和服务器

  • 正确的数据封装

为此,我需要知道如何正确校正主干,并且在开始进行多线程,派生,选择或构建核心之外的东西之前,我想弄清楚基础知识。

我不想超标此帖子,因此,仅在需要时才发布代码。非常感谢您提前阅读和答复。

1 个答案:

答案 0 :(得分:1)

首先,包装所有错误/记录功能始终是一个好习惯,以便可以对其进行修改以便以后扩展。这样做是为了以后,我可以将文件/行添加到我的错误中。

relationship()

关于您的问题。这是一个非常实践的答案。 (最好在this board上提问。但是我仍然会为您提供帮助。

在扩展之前,请确保骨干尽可能牢固。制作精良的应用程序的最佳实践是使其范围非常“平坦”。 (不适用于void perr(char *message) { fprintf(stderr, message); } 中的许多if)。这样做还可以使您更好地了解代码流,并提供更多的原子错误报告:

if

请注意,驱动程序功能(在本示例中为main() { if(!(soc = createsocket(...)) return 1; if(!bindsocket(soc)) { deletesocket(soc); return 1; } // Main server loop while(req = accept_request(soc)) { proc_request(req); } plog("No longer accepting request"); return 0; } )上没有错误报告。这是因为所有错误报告都是在被调用函数(maincreatesocket()等)内部处理的。

仅在调用函数成功与否时才考虑驱动程序函数。每次失败的详细信息都可以在该函数的参数中得到最好的描述。

这是我的提示:

  • 避免使用bindsocket(),如果出现问题,您的代码需要一直准备使用exit()直至return。有执行(线程和子进程,但您知道了)
  • 好的程序善于失败
  • 对于服务器/客户端关系,服务器通常是单线程的,并且仅循环访问所有客户端请求(计算机比您想象的要快,除非您期望大约5k的请求)。
  • 状态机在您的情况下非常有用。考虑一下您的程序将在开始和停止之间所处的状态,列出每种状态下需要使用的方法,并制定一个总体计划,以了解每种状态下发生错误时的情况。 (即main()openedestablishingrunning