Socket communication and string catenation
Dear All, I am trying to implement a client-server model which client tries to accept user input, send the message to the server, and then server append "Echoed from server:" + (client's message) and send back to server, but I do not success using the following codings, is there anyone can do me a favor? I've spent lots of time here :(
Client
/*
* 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) {
perro开发者_运维技巧r("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);
}
Server
/*
* 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);
}
Your programs have a couple of problems that I can see right off the bat.
In
receiver.c
, you're callingstrcat()
with a string literal as the first argument - trying to modify a string literal causes undefined behaviour. Even if you did succeed at modifying it, you're not resetting it before going through the loop again - your output isn't going to look like what you want.In
sender.c
, you're trying to compare strings with the==
operator (the result of thegets()
call and the"."
). That's not going to work. Usestrcmp()
.Don't use
gets()
- it's prone to buffer overflows.fgets()
can be used safely - try that instead.Your
sender.c
program is only reading 1 byte when trying to get the echo back from the server. You need to be trying to receive the whole string you want to get back.
Though you haven't really said what sort of problem you're encountering, one problem is fairly obvious:
while ((gets(ch)) != ".") {
if (write(s, ch, 40) < 0) {
First of all, don't use gets
-- it's just plain evil. Second, when you send the data, you want to send only as much as the user really entered, not necessarily all 40 bytes allocated for the buffer. Third, strings aren't a native type in C -- your comparison with "."
is actually comparing two pointers. Since they'll never have the same address, it'll never return true. Something like the following should at least be a bit closer:
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) {
// ...
精彩评论