我刚开始学习网络编程。我的第一个程序非常简单:一旦连接,服务器程序显示客户端程序发送的内容(字符)。一切正常,直到他们连接起来。起初,我使用putc执行发送循环:
while((c = getc(stdin)) != '\n')
putc(c, (FILE *) connection);
和接收者使用getc:
while((c = getc((FILE *) connection)) != '\n')
putc(c, stdout);
连接后,我遇到了分段错误。然后我尝试使用send:
while(1) {
memset(str, null, strlen(memset));
while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100) {
strcat(str, (char *) c); // cast to char * is to make gcc happy
}
send(connection, (void *) str, sizeof(str), (int) NULL);
}
和recv:
while((stat = recv(connection,str,100,0)) != 0) {
printf("\nReceived %d bytes of data from %s: %s", stat, client, str);
}
现在recv()保持返回-1并且errno设置为107.这是什么意思?我哪里做错了?顺便说一下,我正在使用Linux和gcc。
非常感谢你的帮助! :)
编辑:即使我使用了getc()和putc(),我也会得到socket(),然后我连接()(客户端)。服务器在获得连接(使用socket())bind()之后,然后是listen()和accept()。对不起,如果我捣蛋。
这是服务器代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
void main(int argc, char *argv[])
{
struct addrinfo hint;
struct addrinfo *servinfo, *count;
struct sockaddr_storage conn_addr;
struct sockaddr host;
int connessione;
int stat;
int conn_sock;
int conn_size;
int success;
int c;
char t[INET_ADDRSTRLEN];
char str[100];
char *client;
if(argc != 1 && strcmp(argv[1], "aiuto") == 0) {
printf("%s(porta)\n",argv[0]);
printf("porta: specifica su quale porta installarsi\n");
exit(-1);
}
memset(&hint,0,sizeof hint);
hint.ai_family = AF_INET;
hint.ai_socktype = SOCK_STREAM;
hint.ai_flags = AI_PASSIVE;
if((stat = getaddrinfo(NULL, argv[1], &hint, &servinfo)) != 0) {
printf("\n[FATAL]: getaddrinfo: %s",gai_strerror(stat));
exit(-1);
}
success = 0;
for(count = servinfo; count != NULL; count = count->ai_next) {
if((connessione = socket(count->ai_family, count->ai_socktype, count->ai_protocol)) <= 0)
continue;
if((stat = bind(connessione, count->ai_addr, count->ai_addrlen)) == 0) {
success = 1;
break;
}
else {
continue;
}
}
if(success == 0) {
printf("\n[FATAL]: Unable to bind()!\n");
exit(-1);
}
else {
printf("\n[DEBUG]: %s: listening...", argv[0]);
}
servinfo = count;
freeaddrinfo(count);
if(listen(connessione, 20) == -1) {
printf("\n[FATAL]: listen: %s (%d)\n", gai_strerror(errno), errno);
close(connessione);
exit(-1);
}
conn_size = sizeof(conn_addr);
if(accept(connessione, (struct sockaddr *) &conn_addr, &conn_size) == -1) {
printf("\n[FATAL]: accept: %s", gai_strerror(errno));
close(connessione);
exit(-1);
}
client = (char *) malloc(INET_ADDRSTRLEN * sizeof(char));
client = inet_ntop(servinfo->ai_family, &conn_addr, t, INET_ADDRSTRLEN);
printf("\n[DEBUG]: %s: connection accepted: %s", argv[0], client);
while((stat = recv(connessione,str,100,0)) != 0) {
printf("\nReceived %d bytes of data from %s: %s", stat,client, str);
}
printf("\n[DEBUG]: connection closed by %s\n",client);
}
客户的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
void main(int argc, char *argv[])
{
struct addrinfo hint;
struct addrinfo *servinfo, *count;
struct sockaddr_storage conn_addr;
struct sockaddr host;
int connessione;
int stat;
int conn_sock;
int conn_size;
int success;
int c;
char t[INET_ADDRSTRLEN];
char *indirizzo;
char str[100];
memset(&hint,0,sizeof hint);
host.sa_family = AF_INET;
if(inet_pton(host.sa_family, argv[1], (void *) host.sa_data) == -1) {
printf("\n[FATAL]: pton: %s (%d)\n", gai_strerror(errno), errno);
exit(-1);
}
hint.ai_family = AF_INET;
hint.ai_socktype = SOCK_STREAM;
hint.ai_flags = AI_PASSIVE;
hint.ai_addr = &host;
if((stat = getaddrinfo(argv[1], argv[2], &hint, &servinfo)) != 0) {
printf("[FATAL]: getaddrinfo: %s\n",gai_strerror(stat));
exit(-1);
}
success = 0;
for(count = servinfo; count != NULL; count = count->ai_next) {
if((connessione = socket(count->ai_family, count->ai_socktype, count->ai_protocol)) == -1)
continue;
if(connect(connessione, count->ai_addr, count->ai_addrlen) != -1) {
success = 1;
break;
}
}
if(success == 0) {
printf("\n[FATAL]: impossibile trovare l'host specificato\n");
exit(-1);
}
servinfo = count;
freeaddrinfo(count);
indirizzo = (char *) malloc(INET_ADDRSTRLEN * sizeof(char));
indirizzo = inet_ntop(servinfo->ai_family, &conn_addr, t, INET_ADDRSTRLEN);
printf("\n[DEBUG]: %s: connesso a: %s\n",argv[0], indirizzo);
while(1) {
strcpy(str,"buffer for data to send");
while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100) {
strcat(str, (char *) c);
}
send(connessione, (void *) str, sizeof(str), (int) NULL);
}
}
最后......
完美无缺!感谢大家。 :)
答案 0 :(得分:5)
通常,您不使用FILE *
句柄进行网络编程。相反,您需要socket(2)
系统调用返回的套接字描述符。获得后,您可以connect(2)
它(客户端)或bind(2)
它(服务器)。可以使用recv(2)
和send(2)
执行正在进行的通信。
如果您确实想使用FILE *
句柄进行网络编程,请查看fdopen(3)
库函数。它需要socket(2)
返回的描述符,并返回与FILE *
/ fread
/ fwrite
兼容的fprintf
句柄。
发布完整代码后,我能看到的最重要的错误是:
if (accept(connessione, (struct sockaddr *) &conn_addr, &conn_size))
accept(2)
返回一个必须与recv(2)
/ send(2)
一起使用的套接字,然后使用服务器套接字丢弃它。
答案 1 :(得分:1)
我建议您阅读http://beej.us/guide/
这是一个非常好的套接字编程指南
答案 2 :(得分:1)
当你使用演员表(如(FILE *) connection
)时,你告诉编译器:“相信我,这是事实”。当你欺骗编译器它认为你。
你骗了编译器。 connection
不是指向FILE结构的指针。分段错误是您可以得到的最好的结果,因为它告诉您某些事情是错误的。
答案 3 :(得分:1)
你犯了一些编程错误:
1)memset(str,null,strlen(memset));
should be : memset( str ,0 ,sizeof(str) ); // if str is declared as char str[100];
2)while(((c = getc(stdin))!='\ n')&amp;&amp; sizeof(str)&lt; = 100)
shhould be : while(((c = getc(stdin)) != '\n') && (strlen(str) <= 100))
3)发送(connection,(void *)str,sizeof(str),(int)NULL);
should be : send(connection, (void *) str, strlen(str), (int) NULL);