简单的网络编程程序 - 不起作用
我刚刚开始学习网络编程。我的第一个程序非常简单:连接后,服务器程序显示客户端程序发送的内容(字符)。在连接之前一切正常。首先,我使用 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。这是什么意思?我哪里做错了?顺便说一句,我正在使用带 gcc 的 Linux。
非常感谢您的帮助! :)
编辑:即使我使用 getc() 和 putc(),我也会与 socket() 建立连接,然后我 connect() (客户端)。服务器在获得连接(使用socket())后bind()s,然后是listen()s和accept()s。抱歉,如果我遇见了。
这是服务器代码:
#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);
}
}
最后...
它工作得很好!谢谢大家。 :)
I just began learning network programming. My first program is very simple: once connected, the server program displays what the client program sends (characters). Everything works fine until they get connected. At first, I did the sending loop using putc:
while((c = getc(stdin)) != '\n')
putc(c, (FILE *) connection);
and the receiving one with getc:
while((c = getc((FILE *) connection)) != '\n')
putc(c, stdout);
Once connected, I get a segmentation fault. Then I tried using 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);
}
and recv:
while((stat = recv(connection,str,100,0)) != 0) {
printf("\nReceived %d bytes of data from %s: %s", stat, client, str);
}
Now recv() keeps returning -1 and errno is set to 107. What does this mean? Where am I doing wrong? By the way I'm using Linux with gcc.
Thanks a lot for your help! :)
EDIT: Even if I used getc() and putc(), I get connection with socket(), then I connect() (client). The server, after obtaining connection (with socket()) bind()s, then listen()s and accept()s. Sorry if I ometted.
Here's the server code:
#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);
}
And the client's code:
#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);
}
}
At the end...
It works perfectly! Thanks everyone. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
通常,您不使用
FILE *
句柄进行网络编程。相反,您需要一个由socket(2)
系统调用返回的套接字描述符。获得它后,您可以connect(2)
它(客户端)或bind(2)
它(服务器)。可以使用recv(2)
和send(2)
执行正在进行的通信。如果您确实想使用
FILE *
句柄进行网络编程,请查看fdopen(3)
库函数。它接受一个可以由socket(2)
返回的描述符,并返回一个与fread
/fwrite 兼容的
/FILE *
句柄fprintf
。发布完整代码后,我看到的最重要的错误是:
if (accept(connessione, (struct sockaddr *) &conn_addr, &conn_size))
accept(2)
返回一个必须与recv(2)
/send(2)
一起使用的套接字,然后将其丢弃,改用服务器套接字。Normally you don't use a
FILE *
handle to do network programming. Rather, you need a socket descriptor returned by thesocket(2)
system call. Once you have it, you can eitherconnect(2)
it (the client) orbind(2)
it (the server). The ongoing communication can be performed usingrecv(2)
andsend(2)
.If you really want to use a
FILE *
handle to do network programming, take a look at thefdopen(3)
library function. It takes a descriptor that could be returned bysocket(2)
and returns aFILE *
handle that is compatible withfread
/fwrite
/fprintf
.After posting your full code, the most significant error that I could see was:
if (accept(connessione, (struct sockaddr *) &conn_addr, &conn_size))
accept(2)
returns a socket which you have to use withrecv(2)
/send(2)
, and you discard it, using the server socket instead.我建议您阅读 http://beej.us/guide/
这是一本非常好的套接字编程指南
I suggest You reading http://beej.us/guide/
This is a very nice guide to socket programming
当您使用强制转换(如
(FILE *) 连接
)时,您是在告诉编译器:“相信我,这是事实”。当你对编译器撒谎时,它会相信你。你对编译器撒了谎。
connection
不是指向 FILE 结构的指针。分段错误是您可以获得的最好结果,因为它告诉您出现了严重错误。When you use a cast (like
(FILE *) connection
) you're telling the compiler: "trust me, this is the truth". When you lie to the compiler it believes you.You have lied to the compiler.
connection
is not a pointer to a FILE structure. A segmentation fault is the nicest result you can get, because it tells you something is badly wrong.您犯了一些编程错误:
1)memset(str,null,strlen(memset));
2) while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100)
3) send(connection, (void *) str, sizeof(str), (整数)空);
You make some programming errors:
1) memset(str, null, strlen(memset));
2) while(((c = getc(stdin)) != '\n') && sizeof(str) <= 100)
3) send(connection, (void *) str, sizeof(str), (int) NULL);