Linux网络编程-客户端与服务器端通信

 
Linux网络编程--客户端连接服务器端让我们已经看到了client与server之间是如何建立连接的。接下来介绍它们之间如何建立tcp协议交互通信。
先看看服务器端代码:
###############################tcpserver.c#########################
 

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main() {
  int ld,sd;
  struct sockaddr_in skaddr;
  struct sockaddr_in from;
  socklen_t addrlen, length;

  char buff[100],send_message[100];
  int n;
//建立一个socket
  if ((ld = socket (PF_INET, SOCK_STREAM, 0))<0) {
    perror("Problem creating socket/n");
    exit(1);
  }

  skaddr.sin_family = AF_INET;
  skaddr.sin_addr.s_addr = htonl (INADDR_ANY);//可以同任意主机通讯
  skaddr.sin_port = htons(0);//任何指派一个端口b

  if(bind(ld,(struct sockaddr *)&skaddr, sizeof (skaddr))<0){
    perror("Problem binding/n");
    exit(0);
  }

  length = sizeof (skaddr);
  if (getsockname(ld, (struct sockaddr *)&skaddr, &length) <0) {
     perror("Error getsockname/n");
     exit(1);
  }
  printf("The Server passive socket port number is %d/n",
ntohs(skaddr.sin_port));//打印出随机的端口

  if (listen(ld,5)<0) {
     perror("Error calling listen/n");
     exit(1);
  }

  while (1) {
    printf("Ready for a connection ... /n");
    addrlen=sizeof(skaddr);
    if((sd = accept (ld, (struct sockaddr*) &from, &addrlen)) <0) {
       perror("Problem with accept call/n");
       exit(1);
    }

   printf("Got a connect - processing .../n");
   length = sizeof (skaddr);
   if (getsockname (sd, (struct sockaddr*)&skaddr, &length)<0) {
      perror ("Error getsockname/n");
      exit(1);
   }

   printf("The active server port number is %d/n", ntohs
(skaddr.sin_port));
   printf("The active server IP ADDRESS is %s/n" ,inet_ntoa
(skaddr.sin_addr));

  printf("The client port number is %d/n", ntohs(from.sin_port));
  printf("The client IP ADDRESS is %s/n",inet_ntoa(from.sin_addr));

  while ((n=read(sd,buff,100))>0) {//一旦缓冲区部为空的时候读出数据
    printf("%s/n","Client say:");
    write (1,buff,n);
    printf("%s/n","Server say:");
    fgets(send_message,100,stdin);
    write (sd,send_message,strlen(send_message));
  }

  printf("Done with connection -closing/n/n/n");
  close (sd);
  }
}

 

从服务器端的代码可以看出:与客户端的交流是比较不灵活的,因为当server读出client发送过来的buff,将结果显示出来之后,打 印"Server say:"接着执行fget操作,等待用户输入资料。此时client可能就无法输入或者发送新的buff给server.接下来看看client代码:

########################tcpclient.c###########################

 

#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /*needed for atoi() */
#include <unistd.h> /*Unix System Calls */
#include <sys/types.h> /*system data type definition */
#include <netinet/in.h> /* INET constants and stuff */
#include <sys/socket.h> /* socket specific definitions */
#include <arpa/inet.h> /*IP address conversion stuff */

char message_recv[100];
char message_send[100];

int main( int argc, char **argv) {
   int sk;
   struct sockaddr_in skaddr;

   if (argc != 3) {
      printf("Usage: client <server name> <server port>/n");
      exit(0);
   }

   if ((sk =socket(PF_INET, SOCK_STREAM, 0)) <0 ) {
      printf("Problem creating socket /n");
      exit(1);
   }

   skaddr.sin_family = AF_INET;

   if (inet_aton(argv[1], &skaddr.sin_addr) ==0) {
      printf("Invalid IP address : %s/n", argv[1]);//ip address
      exit(1);
   }

   skaddr.sin_port = htons (atoi(argv [2]));//port number

   if (connect (sk, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) {
      printf("Problem connecting socket /n");
      exit(1);
   }

   while (1){
       printf("%s/n","Client says:");
       fgets(message_send,sizeof(message_send),stdin);
       write(sk, message_send, strlen(message_send));
       read (sk, message_recv, 100);
       printf("%s/n","Server says:");
       write(1, message_recv,100);
   }

   close(sk);
   return(0);
}

 

客户端的while下的操作与server相差无几。所以彼此之间的操作正如前面所说的。不灵活。不能彼此随心所欲的童心。

执行程序:

服务器端:

bash-2.05a$ gcc -o tcpclient tcpclient.c

bash-2.05a$ ./tcpserver
The Server passive socket port number is 53180
Ready for a connection ...
Got a connect - processing ...

The active server port number is 53180
The active server IP ADDRESS is 127.0.0.1
The client port number is 53181
The client IP ADDRESS is 127.0.0.1
Client say:
hello
Server say:

what can i do for u sir

客户端:

bash-2.05a$gcc -o tcpclient tcpclient.c

bash-2.05a$ ./tcpclient 127.0.0.1 53180

Client says:
hello
Server says:
what can i do for u sir
Client says:

如果客户端执行命令行为:bash-2.05a$ ./tcpclient localhost 53180

就会出现如下的错误:
Invalid IP address : localhost

问题很简单:在相当于地址解析错误。gethostname()可以帮助我们解决问题:

####################tcpclient1.c#########################

#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /*needed for atoi() */
#include <unistd.h> /*Unix System Calls */
#include <sys/types.h> /*system data type definition */
#include <netinet/in.h> /* INET constants and stuff */
#include <sys/socket.h> /* socket specific definitions */
#include <arpa/inet.h> /*IP address conversion stuff */
#include <netdb.h> /* Name lookups (gethostbyname) */

char message_recv[100];
char message_send[100];

int main( int argc, char **argv) {
   int sk;
   struct sockaddr_in skaddr;
   struct hostent *hp;

   if (argc != 3) {
      printf("Usage: client <server name> <server port>/n");
      exit(0);
   }

   if ((sk =socket(PF_INET, SOCK_STREAM, 0)) <0 ) {
      printf("Problem creating socket /n");
      exit(1);
   }

   skaddr.sin_family = AF_INET;

   if (( hp= gethostbyname(argv[1])) !=0){//地址解析
   memcpy( &skaddr.sin_addr.s_addr, hp->h_addr, hp->h_length);
   }
   else
   {

   if (inet_aton(argv[1], &skaddr.sin_addr) ==0) {
      printf("Invalid IP address : %s/n", argv[1]);
      exit(1);
   }
   }

   skaddr.sin_port = htons (atoi(argv [2]));

   if (connect (sk, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) {
      printf("Problem connecting socket /n");
      exit(1);
   }

   while (1){
       printf("%s/n","Client says:");
       fgets(message_send,sizeof(message_send),stdin);
       write(sk, message_send, strlen(message_send));
       read (sk, message_recv, 100);
       printf("%s/n","Server says:");
       write(1, message_recv,100);
   }

   close(sk);
   return(0);
}

 

这样地址解析的问题就可以得到解决了。

客户端:

bash-2.05a$ ./tcpclient1 127.0.0.1 53194
Client says:
lsdf
^[[A^C
bash-2.05a$ ./tcpclient1 localhost 53194
Client says://这里不再提是错误
fgf

-------------------------ENJOY-------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值