【问题标题】:C server crashes after Java client connectsJava客户端连接后C服务器崩溃
【发布时间】:2012-03-04 07:29:24
【问题描述】:

我正在使用 C 线程服务器和 java 客户端处理这个示例。这是服务器:

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>

void* thread_proc(void *arg);

int main(int argc, char *argv[])
{
    struct sockaddr_in sAddr;
    int listensock;
    int result;
    int nchildren = 6;
    pthread_t thread_id;
    int x;
    int val;

    listensock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    val = 1;
    result = setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
    if (result < 0) {
        perror("server");
        return 0;
    }

    sAddr.sin_family = AF_INET;
    sAddr.sin_port = htons(6000);
    sAddr.sin_addr.s_addr = INADDR_ANY;

    result = bind(listensock, (struct sockaddr *) &sAddr, sizeof(sAddr));
    if (result < 0) {
        perror("exserver5");
        return 0;
    }

    result = listen(listensock, 5);
    if (result < 0) {
        perror("exserver5");
        return 0;
    }

   for (x = 0; x < nchildren; x++) {
    result = pthread_create(&thread_id, NULL, thread_proc, (void *) listensock);
    if (result != 0) {
      printf("Could not create thread.\n");
      return 0;
    }
    sched_yield();
    }

   pthread_join (thread_id, NULL);
}

void* thread_proc(void *arg)
{
  int listensock, sock;
  char buffer[25];
  int nread;

  listensock = (int) arg;

  while (1) {
    sock = accept(listensock, NULL, NULL);
    printf("client connected to child thread %i with pid %i.\n", pthread_self(), getpid());

    while(1){
        nread = recv(sock, buffer, 25, 0);
        buffer[nread] = '\0';
        printf("%s\n", buffer);
        send(sock, buffer, nread, 0);
        if(nread == '9'){
        close(sock);
        }
        }

    printf("client disconnected from child thread %i with pid %i.\n", pthread_self(), getpid());
  }
}

这是 Java 客户端:

import java.net.*;
import java.io.*;

// A client for our multithreaded EchoServer.
public class client
{
    public static void main(String[] args)
    {
        Socket s = null;

        // Create the socket connection to the EchoServer.
        try
        {
            s = new Socket("localhost", 6000);
        }        
        catch(UnknownHostException uhe)
        {
            // Host unreachable
            System.out.println("Unknown Host");
            s = null;
        }
        catch(IOException ioe)
        {
            // Cannot connect to port on given host
            System.out.println("Cant connect to server at 6000. Make sure it is running.");
            s = null;
        }

        if(s == null)
            System.exit(-1);

        BufferedReader in = null;
        PrintWriter out = null;

        try
        {
            // Create the streams to send and receive information
            in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));

            // Since this is the client, we will initiate the talking.
            // Send a string.
            out.println("Hello");
            out.flush();
            // receive the reply.
            System.out.println("Server Says : " + in.readLine());

            // Send a string.
            out.println("This");
            out.flush();
            // receive a reply.
            System.out.println("Server Says : " + in.readLine());

            // Send a string.
            out.println("is");
            out.flush();
            // receive a reply.
            System.out.println("Server Says : " + in.readLine());

            // Send a string.
            out.println("a");
            out.flush();
            // receive a reply.
            System.out.println("Server Says : " + in.readLine());

            // Send a string.
            out.println("Test");
            out.flush();
            // receive a reply.
            System.out.println("Server Says : " + in.readLine());

            // Send the special string to tell server to quit.
            out.println("9");
            out.flush();
        }
        catch(IOException ioe)
        {
            System.out.println("Exception during communication. Server probably closed connection.");
        }
        finally
        {
            try
            {
                // Close the streams
                out.close();
                in.close();
                // Close the socket before quitting
                s.close();
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }                
        }        
    }
} 

当我运行客户端时,这是输出:

[root@localhost java]# /opt/jdk1.7.0_03/bin/java client
Server Says : Hello
Server Says : This
Server Says : is
Server Says : a
Server Says : Test
[root@localhost java]# 

当我运行服务器时,这是输出:

[root@localhost java]# ./server 
client connected to child thread -1215423632 with pid 2854.
Hello

This

is

a

Test

9

9

[root@localhost java]# 

当客户端关闭连接时,服务器崩溃。我想在不破坏线程的情况下关闭连接。我该如何解决这个问题?

最好的祝福

P.S 这是接受连接的原始线程代码。

void* thread_proc(void *arg)
{
  int listensock, sock;
  char buffer[25];
  int nread;

  listensock = (int) arg;

  while (1) {
    sock = accept(listensock, NULL, NULL);
    printf("client connected to child thread %i with pid %i.\n", pthread_self(), getpid());
    nread = recv(sock, buffer, 25, 0);
    buffer[nread] = '\0';
    printf("%s\n", buffer);
    send(sock, buffer, nread, 0);
    close(sock);
    printf("client disconnected from child thread %i with pid %i.\n", pthread_self(), getpid());
  }
}

这个循环将只接受一个字符串并将其返回。然后会退出。我用一个while循环修改它,但用内部while循环(见上文)服务器崩溃。 我如何修改代码以便线程可以接受许多字符串并发送许多字符串?

【问题讨论】:

    标签: java c compilation network-programming


    【解决方案1】:

    您需要在关闭套接字后跳出内部循环 - 您在尝试从已关闭的套接字中读取时崩溃:

    while(1){
            nread = recv(sock, buffer, 25, 0);
            buffer[nread] = '\0';
            printf("%s\n", buffer);
            send(sock, buffer, nread, 0);
            if(nread == '9'){
                close(sock);
                break;       // <--- need to break out here
            }
        }
    

    【讨论】:

    • 并且应该检查recv是否返回0(意味着另一端关闭了连接)或-1(错误)。 nread == '9' 也有可能是错误的,因为它检查接收到的字节数是否为 57。
    • +1 不错的收获。但是,这将使线程退出,这不是 OP 想要的
    • 购买方式没有变化。服务器再次崩溃。
    • 您可能应该正确处理错误。您的客户端发送一个“9”然后关闭连接。服务器读取“9”,然后尝试在客户端刚刚关闭的连接上发送。这会导致错误。
    • 你至少应该检查 recv() 没有重新调整 -1(它在失败时会这样做),会崩溃设置缓冲区 [-1]。
    【解决方案2】:
    while (1) {
        sock = accept(listensock, NULL, NULL);
        printf("client connected to child thread %i with pid %i.\n", pthread_self(), getpid());
    
        nread = 0;
        while(nread >= 0) {
            nread = recv(sock, buffer, 25, 0);
            if (nread >= 0) {
                buffer[nread] = '\0';
                printf("%s\n", buffer);
                send(sock, buffer, nread, 0);
            }
        }
        close(sock);
        printf("client disconnected from child thread %i with pid %i.\n", pthread_self(), getpid());
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      相关资源
      最近更新 更多