亲爱的, 我正在尝试实现一个客户端 - 服务器模型,客户端尝试接受用户输入,将消息发送到服务器,然后服务器追加“Echoed from server:”+(客户端的消息)并发送回服务器,但我不使用以下编纂成功,是否有人可以帮我一个忙?我在这里度过了很多时间:(
客户端
/*
* Usage: sender [host]
*
* General description of code:
* (1) Create a local socket, specifying domain and protocol
* (2) Set up the remote address
* (3) Connect to it
* (4) Send/recv data to server
* (5) Close connection
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define PORT 5667
main(argc, argv)
int argc;
char *argv[];
{
int s;
struct hostent *remote_ent;
struct sockaddr_in remote_addr;
char ch[40];
if (argc != 2) {
printf("usage: sender hostname \n"); exit(1);
}
/* (1) Create the socket */
if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("Can't create send_socket"); exit(1);
}
/* (2) Assign the remote address */
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(PORT);
if ((remote_ent = gethostbyname(argv[1])) == NULL) {
perror("Can't get remote host address"); exit(1);
}
bcopy(remote_ent->h_addr_list[0],
&remote_addr.sin_addr, remote_ent->h_length);
/* (3) Connect to remote socket */
if (connect(s, &remote_addr, sizeof(remote_addr)) < 0) {
perror("Can't connect to remote address"); exit(1);
}
/* (4) Send /recv data thru socket */
while ((gets(ch)) != ".") {
if (write(s, ch, 40) < 0) {
perror("write error"); exit(1);
}
read(s, ch, 1);
puts(ch);
}
/* (5) Close and exit */
close(s); /* close remote socket as well */
exit(0);
}
服务器
/*
* receiver.c
*
* Receiver (server) half of a pair of sockets.
* Note: receiver is already multi-threading!
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define PORT 5667 /* by Kei */
main() {
int s, new_s;
int remote_addr_len;
struct sockaddr_in local_addr, remote_addr;
char ch[40];
char *ch2 = "Echoed from server:";
/* (1) Create the socket */
if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("Can't create s");
exit(1);
}
bzero(&local_addr,sizeof(local_addr));
/* (2) Set up the address */
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(PORT); /* port#, no need of IP addr */
/* (3) Bind local address to this socket */
if (bind(s, &local_addr, sizeof(local_addr)) < 0) {
perror("Can't bind socket to local address"); exit(1);
}
/* (4) Wait for a connection (only 1 pending allowed)*/
if (listen(s, 1) < 0) {
perror("listen failed"); exit(1);
}
while (1) { /* wait for connection, recv and reply */
/* (5) Accept connection */
if ((new_s = accept(s, &remote_addr, &remote_addr_len))<0) {
perror("Can't accept connection"); exit(1);
}
/* IP-addr & port # of the remote socket */
printf("remote IP: %d.%d.%d.%d\n",
remote_addr.sin_addr._S_un._S_un_b.s_b1,
remote_addr.sin_addr._S_un._S_un_b.s_b2,
remote_addr.sin_addr._S_un._S_un_b.s_b3,
remote_addr.sin_addr._S_un._S_un_b.s_b4);
printf("remote port: %d\n", remote_addr.sin_port);
/* (6) Exchange data. Socket is Bi-directional! */
while (read(new_s, ch, 40) > 0) {
strcat(ch2,ch);
if (write(new_s, ch2, 40) < 0) {
perror("write error"); exit(1); }
puts(ch); /* put on screen */
}
close(new_s);
}
/* (7) Close and exit */
close(s);
exit(0);
}
答案 0 :(得分:1)
你的程序有几个我可以立即看到的问题。
在receiver.c
中,您使用字符串文字作为第一个参数调用strcat()
- 尝试修改字符串文字会导致未定义的行为。即使你确实成功修改它,你也不会在重新循环之前重置它 - 你的输出看起来不像你想要的那样。
在sender.c
中,您尝试将字符串与==
运算符(gets()
调用的结果和"."
)进行比较。那不行。使用strcmp()
。
不要使用gets()
- 它容易出现缓冲区溢出。 fgets()
可以安全使用 - 请尝试使用。
当您尝试从服务器获取回显时,您的sender.c
程序只读取1个字节。您需要尝试接收想要返回的整个字符串。
答案 1 :(得分:1)
虽然你还没有真正说过你遇到的问题,但有一个问题是显而易见的:
while ((gets(ch)) != ".") {
if (write(s, ch, 40) < 0) {
首先,不要使用gets
- 它只是简单的邪恶。其次,当您发送数据时,您希望仅发送用户真正输入的数量,而不是必须为缓冲区分配所有40个字节。第三,字符串不是C中的本机类型 - 与"."
的比较实际上是比较两个指针。因为它们永远不会有相同的地址,所以永远不会真实。像下面这样的东西至少应该更接近:
while (fgets(ch, sizeof(ch), stdin) && strcmp(ch, ".\n")) {
strtok(ch, "\n"); // the oddball but useful purpose for `strtok`.
if (write(s, ch, strlen(ch))<0) {
// ...