我对 C 和 Linux 还很陌生,我尝试设置一个 TCP 套接字服务器,使用我在 Ubuntu 系统上编译和执行的 C 代码进行数据交换。
从教程中,我复制了以下代码(见下文),它可以启动服务器并使用客户端代码接收数据(时间和日期)(在同一台机器上用于测试目的)。
然后我重新启动了Ubuntu机器,从那以后我就无法再启动服务器了。
然后我在下面的代码中添加了异常处理,它抛出“无法绑定”错误号 22,这意味着“参数无效”?这对我来说没有意义,因为相同的代码以前工作得很好。
我假设“旧”套接字处于时间等待状态或尚未关闭,但我使用“ss -all state xxx”检查了所有不同状态的所有连接,一切似乎都正常。
还尝试使用不同的端口和代码 - 同样的问题。
希望任何人都可以帮助我解决这个问题,因为我不知道还能尝试什么。
// C-Code Server
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
//Open a socket
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
if (listenfd == -1) {
printf("Error: unable to open a socket\n");
exit(1);
}
//Create an Adress
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htons(INADDR_ANY);
serv_addr.sin_port = htons(1234);
//Macht schon benutzte Adresse mit SO_REUSEADDR nutzbar
int opt = 1;
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))<0) {
perror("setsockopt");exit(EXIT_FAILURE);
}
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(opt))<0) {
perror("setsockopt");exit(EXIT_FAILURE);
}
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if ((bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) == -1) {
printf("Error: unable to bind\n");
printf("Error code: %d\n", errno);
exit(1);
}
listen(listenfd, 10);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
if (connfd == -1) {
printf("Error: unable to accept connections\n");
printf("Error code: %d\n", errno);
exit(1);
}
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
答案1
绑定(2)告诉:
EINVAL The socket is already bound to an address.
事实上,您在同一个套接字上调用了两次bind():
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); if ((bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) == -1) { printf("Error: unable to bind\n"); printf("Error code: %d\n", errno); exit(1); }
一旦第一个bind()被删除,我就可以在连接时收到日期。